RavEngine
Loading...
Searching...
No Matches
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>
153using IsCopyAssignableImpl =
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
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>
404inline void AssertHashEnabled
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>
424struct hash_policy_traits
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.
466 using constant_iterators = ConstantIteratorsImpl<>;
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>
601using identity_t = typename identity<T>::type;
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,
861 DataMemAndPtr, Callable>::type>::type>::
862 type>::type type;
863};
864
865// The result type of Invoke<F, Args...>.
866template <typename F, typename... Args>
867using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
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>
958using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
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>
966using make_index_sequence = make_integer_sequence<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>
974using index_sequence_for = make_index_sequence<sizeof...(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
992PHMAP_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
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))...)) {
1050 return phmap::base_internal::Invoke(
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)
1098 -> decltype(utility_internal::apply_helper(
1099 phmap::forward<Functor>(functor), phmap::forward<Tuple>(t),
1100 phmap::make_index_sequence<std::tuple_size<
1101 typename std::remove_reference<Tuple>::type>::value>{})) {
1102 return utility_internal::apply_helper(
1103 phmap::forward<Functor>(functor), phmap::forward<Tuple>(t),
1104 phmap::make_index_sequence<std::tuple_size<
1105 typename std::remove_reference<Tuple>::type>::value>{});
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>
1179 typename memory_internal::MakeUniqueResult<T>::scalar make_unique(
1180 Args&&... args) {
1181 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
1182 }
1183
1184 template <typename T>
1185 typename memory_internal::MakeUniqueResult<T>::array make_unique(size_t n) {
1186 return std::unique_ptr<T>(new typename phmap::remove_extent_t<T>[n]());
1187 }
1188
1189 template <typename T, typename... Args>
1190 typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
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>
1228using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type;
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>
1250using GetPropagateOnContainerCopyAssignment =
1251 typename T::propagate_on_container_copy_assignment;
1252
1253template <typename T>
1254using GetPropagateOnContainerMoveAssignment =
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>
1273 using type = typename GetFirstArg<Ptr>::type;
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>
1292 using type = typename RebindFirstArg<T, U>::type;
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)>
1312 using type = typename RebindFirstArg<T, U>::type;
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...>
1331 using element_type = typename memory_internal::ElementType<Ptr>::type;
1332
1333 // difference_type:
1334 // Ptr::difference_type if present, otherwise std::ptrdiff_t
1335 using difference_type =
1336 memory_internal::ExtractOrT<memory_internal::GetDifferenceType, Ptr,
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>
1343 using rebind = typename memory_internal::RebindPtr<Ptr, U>::type;
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)
1365 static pointer pointer_to(
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*
1388 using pointer = memory_internal::ExtractOrT<memory_internal::GetPointer,
1389 Alloc, value_type*>;
1390
1391 // const_pointer:
1392 // Alloc::const_pointer if present, otherwise
1393 // phmap::pointer_traits<pointer>::rebind<const value_type>
1394 using const_pointer =
1395 memory_internal::ExtractOrT<memory_internal::GetConstPointer, Alloc,
1397 template rebind<const value_type>>;
1398
1399 // void_pointer:
1400 // Alloc::void_pointer if present, otherwise
1401 // phmap::pointer_traits<pointer>::rebind<void>
1402 using void_pointer = memory_internal::ExtractOrT<
1403 memory_internal::GetVoidPointer, Alloc,
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>
1409 using const_void_pointer = memory_internal::ExtractOrT<
1410 memory_internal::GetConstVoidPointer, Alloc,
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
1416 using difference_type = memory_internal::ExtractOrT<
1417 memory_internal::GetDifferenceType, Alloc,
1418 typename phmap::pointer_traits<pointer>::difference_type>;
1419
1420 // size_type:
1421 // Alloc::size_type if present, otherwise
1422 // std::make_unsigned<difference_type>::type
1423 using size_type = memory_internal::ExtractOrT<
1424 memory_internal::GetSizeType, Alloc,
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
1430 using propagate_on_container_copy_assignment = memory_internal::ExtractOrT<
1431 memory_internal::GetPropagateOnContainerCopyAssignment, Alloc,
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
1437 using propagate_on_container_move_assignment = memory_internal::ExtractOrT<
1438 memory_internal::GetPropagateOnContainerMoveAssignment, Alloc,
1439 std::false_type>;
1440
1441 // propagate_on_container_swap:
1442 // Alloc::propagate_on_container_swap if present, otherwise std::false_type
1443 using propagate_on_container_swap =
1444 memory_internal::ExtractOrT<memory_internal::GetPropagateOnContainerSwap,
1445 Alloc, std::false_type>;
1446
1447 // is_always_equal:
1448 // Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type
1449 using is_always_equal =
1450 memory_internal::ExtractOrT<memory_internal::GetIsAlwaysEqual, Alloc,
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>
1457 using rebind_alloc = typename memory_internal::RebindAlloc<Alloc, T>::type;
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) {
1512 return select_on_container_copy_construction_impl(0, a);
1513 }
1514
1515private:
1516 template <typename A>
1517 static auto allocate_impl(int, A& a, // NOLINT(runtime/references)
1518 size_type n, const_void_pointer hint)
1519 -> decltype(a.allocate(n, hint)) {
1520 return a.allocate(n, hint);
1521 }
1522 static pointer allocate_impl(char, Alloc& a, // NOLINT(runtime/references)
1523 size_type n, const_void_pointer) {
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>
1558 static auto select_on_container_copy_construction_impl(int, const A& a)
1559 -> decltype(a.select_on_container_copy_construction()) {
1560 return a.select_on_container_copy_construction();
1561 }
1562 static Alloc select_on_container_copy_construction_impl(char,
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) {
1615 PHMAP_INTERNAL_TRY {
1616 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1617 args...);
1618 }
1619 PHMAP_INTERNAL_CATCH_ANY {
1620 while (cur != first) {
1621 --cur;
1622 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1623 }
1624 PHMAP_INTERNAL_RETHROW;
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)) {
1635 PHMAP_INTERNAL_TRY {
1636 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
1637 *first);
1638 }
1639 PHMAP_INTERNAL_CATCH_ANY {
1640 while (cur != destination) {
1641 --cur;
1642 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
1643 }
1644 PHMAP_INTERNAL_RETHROW;
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:
1686 bad_optional_access() = default;
1687 ~bad_optional_access() override;
1688 const char* what() const noexcept override;
1689};
1690
1691template <typename T>
1692class optional;
1693
1694// --------------------------------
1695struct nullopt_t
1696{
1697 struct init_t {};
1698 static init_t init;
1699
1700 explicit constexpr nullopt_t(init_t& /*unused*/) {}
1701};
1702
1703constexpr nullopt_t nullopt(nullopt_t::init);
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.
1727 bool engaged_;
1728 // Data storage
1729 union {
1730 dummy_type dummy_;
1731 T data_;
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
1748 ~optional_data_dtor_base() { destruct(); }
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.
1763 bool engaged_;
1764 // Data storage
1765 union {
1766 dummy_type dummy_;
1767 T data_;
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
1787 optional_data_base() = default;
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>
1825class optional_data<T, true> : public optional_data_base<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>
1840class optional_data<T, false> : public optional_data_base<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
1859 optional_data(optional_data&& rhs) noexcept(
1860 phmap::default_allocator_is_nothrow::value ||
1861 std::is_nothrow_move_constructible<T>::value)
1863 if (rhs.engaged_) {
1864 this->construct(std::move(rhs.data_));
1865 }
1866 }
1867
1868 optional_data& operator=(const optional_data& rhs) {
1869 if (rhs.engaged_) {
1870 this->assign(rhs.data_);
1871 } else {
1872 this->destruct();
1873 }
1874 return *this;
1875 }
1876
1877 optional_data& operator=(optional_data&& rhs) noexcept(
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 <>
1898class optional_ctor_base<copy_traits::copyable>
1899{
1900public:
1901 constexpr optional_ctor_base() = default;
1902 optional_ctor_base(const optional_ctor_base&) = default;
1904 optional_ctor_base& operator=(const optional_ctor_base&) = default;
1905 optional_ctor_base& operator=(optional_ctor_base&&) = default;
1906};
1907
1908template <>
1909class optional_ctor_base<copy_traits::movable>
1910{
1911public:
1912 constexpr optional_ctor_base() = default;
1913 optional_ctor_base(const optional_ctor_base&) = delete;
1915 optional_ctor_base& operator=(const optional_ctor_base&) = default;
1916 optional_ctor_base& operator=(optional_ctor_base&&) = default;
1917};
1918
1919template <>
1920class optional_ctor_base<copy_traits::non_movable>
1921{
1922public:
1923 constexpr optional_ctor_base() = default;
1924 optional_ctor_base(const optional_ctor_base&) = delete;
1926 optional_ctor_base& operator=(const optional_ctor_base&) = default;
1927 optional_ctor_base& operator=(optional_ctor_base&&) = default;
1928};
1929
1930// Base class for enabling/disabling copy/move assignment.
1931template <copy_traits>
1933
1934template <>
1935class optional_assign_base<copy_traits::copyable>
1936{
1937public:
1938 constexpr optional_assign_base() = default;
1941 optional_assign_base& operator=(const optional_assign_base&) = default;
1942 optional_assign_base& operator=(optional_assign_base&&) = default;
1943};
1944
1945template <>
1946class optional_assign_base<copy_traits::movable>
1947{
1948public:
1949 constexpr optional_assign_base() = default;
1952 optional_assign_base& operator=(const optional_assign_base&) = delete;
1953 optional_assign_base& operator=(optional_assign_base&&) = default;
1954};
1955
1956template <>
1957class optional_assign_base<copy_traits::non_movable>
1958{
1959public:
1960 constexpr optional_assign_base() = default;
1963 optional_assign_base& operator=(const optional_assign_base&) = delete;
1964 optional_assign_base& operator=(optional_assign_base&&) = delete;
1965};
1966
1967template <typename T>
1968constexpr copy_traits get_ctor_copy_traits()
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>
1977constexpr copy_traits get_assign_copy_traits()
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.
2013bool convertible_to_bool(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>
2021{
2022 optional_hash_base() = delete;
2023 optional_hash_base(const optional_hash_base&) = delete;
2025 optional_hash_base& operator=(const optional_hash_base&) = delete;
2026 optional_hash_base& operator=(optional_hash_base&&) = delete;
2027};
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{
2033 using argument_type = phmap::optional<T>;
2034 using result_type = size_t;
2035 size_t operator()(const phmap::optional<T>& opt) const {
2036 phmap::type_traits_internal::AssertHashEnabled<phmap::remove_const_t<T>>();
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>
2053class optional : private optional_internal::optional_data<T>,
2055 optional_internal::get_ctor_copy_traits<T>()>,
2057 optional_internal::get_assign_copy_traits<T>()>
2058{
2059 using data_base = optional_internal::optional_data<T>;
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,
2084 phmap::enable_if_t<phmap::conjunction<
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>
2174 optional(optional<U>&& rhs) {
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&&>,
2187 optional_internal::is_constructible_convertible_from_optional<
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 = { };
2208 optional& operator=(nullopt_t) noexcept {
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>
2229 optional& operator=(U&& v) {
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>
2243 optional& operator=(const optional<U>& rhs) {
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>
2260 optional& operator=(optional<U>&& rhs) {
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 }
2354 T* operator->() {
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>
2505constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
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 <>
2730struct KeyArg<false>
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>
2748class node_handle_base
2749{
2750protected:
2751 using slot_type = typename PolicyTraits::slot_type;
2752
2753public:
2754 using allocator_type = Alloc;
2755
2756 constexpr node_handle_base() {}
2757
2758 node_handle_base(node_handle_base&& other) noexcept {
2759 *this = std::move(other);
2760 }
2761
2762 ~node_handle_base() { destroy(); }
2763
2764 node_handle_base& operator=(node_handle_base&& other) noexcept {
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(); }
2776 allocator_type get_allocator() const { return *alloc_; }
2777
2778protected:
2779 friend struct CommonAccess;
2780
2782 node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s)
2783 : alloc_(a) {
2784 PolicyTraits::transfer(alloc(), slot(), s);
2785 }
2786
2787 struct move_tag_t {};
2788 node_handle_base(move_tag_t, const allocator_type& a, slot_type* s)
2789 : alloc_(a) {
2790 PolicyTraits::construct(alloc(), slot(), s);
2791 }
2792
2793 node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
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());
2809 alloc_ = phmap::nullopt;
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:
2820 phmap::optional<allocator_type> alloc_;
2821 mutable phmap::aligned_storage_t<sizeof(slot_type), alignof(slot_type)> slot_space_;
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{
2834 using Base = node_handle_base<PolicyTraits, Alloc>;
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{
2858 using Base = node_handle_base<PolicyTraits, Alloc>;
2859
2860public:
2861 using key_type = typename Policy::key_type;
2862 using mapped_type = typename Policy::mapped_type;
2863
2864 constexpr node_handle() {}
2865
2866 auto key() const -> decltype(PolicyTraits::key(this->slot())) {
2867 return PolicyTraits::key(this->slot());
2868 }
2869
2870 mapped_type& mapped() const {
2871 return PolicyTraits::value(&PolicyTraits::element(this->slot()));
2872 }
2873
2874private:
2875 friend struct CommonAccess;
2876
2877 using Base::Base;
2878};
2879
2880// Provide access to non-public node-handle functions.
2881struct CommonAccess
2882{
2883 template <typename Node>
2884 static auto GetSlot(const Node& node) -> decltype(node.slot()) {
2885 return node.slot();
2886 }
2887
2888 template <typename Node>
2889 static void Destroy(Node* node) {
2890 node->destroy();
2891 }
2892
2893 template <typename Node>
2894 static void Reset(Node* node) {
2895 node->reset();
2896 }
2897
2898 template <typename T, typename... Args>
2899 static T Make(Args&&... args) {
2900 return T(std::forward<Args>(args)...);
2901 }
2902
2903 template <typename T, typename... Args>
2904 static T Transfer(Args&&... args) {
2905 return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);
2906 }
2907
2908 template <typename T, typename... Args>
2909 static T Move(Args&&... args) {
2910 return T(typename T::move_tag_t{}, std::forward<Args>(args)...);
2911 }
2912};
2913
2914// Implement the insert_return_type<> concept of C++17.
2915template <class Iterator, class NodeType>
2916struct InsertReturnType
2917{
2918 Iterator position;
2919 bool inserted;
2920 NodeType node;
2921};
2922
2923} // namespace priv
2924} // namespace phmap
2925
2926
2927#ifdef ADDRESS_SANITIZER
2928 #include <sanitizer/asan_interface.h>
2929#endif
2930
2931// ---------------------------------------------------------------------------
2932// span.h
2933// ---------------------------------------------------------------------------
2934
2935namespace phmap {
2936
2937template <typename T>
2938class Span;
2939
2940namespace span_internal {
2941// A constexpr min function
2942constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
2943
2944// Wrappers for access to container data pointers.
2945template <typename C>
2946constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
2947 -> decltype(c.data()) {
2948 return c.data();
2949}
2950
2951// Before C++17, std::string::data returns a const char* in all cases.
2952inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
2953 int) noexcept {
2954 return &s[0];
2955}
2956
2957template <typename C>
2958constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
2959 -> decltype(GetDataImpl(c, 0)) {
2960 return GetDataImpl(c, 0);
2961}
2962
2963// Detection idioms for size() and data().
2964template <typename C>
2965using HasSize =
2966 std::is_integral<phmap::decay_t<decltype(std::declval<C&>().size())>>;
2967
2968// We want to enable conversion from vector<T*> to Span<const T* const> but
2969// disable conversion from vector<Derived> to Span<Base>. Here we use
2970// the fact that U** is convertible to Q* const* if and only if Q is the same
2971// type or a more cv-qualified version of U. We also decay the result type of
2972// data() to avoid problems with classes which have a member function data()
2973// which returns a reference.
2974template <typename T, typename C>
2975using HasData =
2976 std::is_convertible<phmap::decay_t<decltype(GetData(std::declval<C&>()))>*,
2977 T* const*>;
2978
2979// Extracts value type from a Container
2980template <typename C>
2982 using type = typename phmap::remove_reference_t<C>::value_type;
2983};
2984
2985template <typename T, size_t N>
2986struct ElementType<T (&)[N]> {
2987 using type = T;
2988};
2989
2990template <typename C>
2991using ElementT = typename ElementType<C>::type;
2992
2993template <typename T>
2994using EnableIfMutable =
2995 typename std::enable_if<!std::is_const<T>::value, int>::type;
2996
2997template <typename T>
2998bool EqualImpl(Span<T> a, Span<T> b) {
2999 static_assert(std::is_const<T>::value, "");
3000 return std::equal(a.begin(), a.end(), b.begin(), b.end());
3001}
3002
3003template <typename T>
3004bool LessThanImpl(Span<T> a, Span<T> b) {
3005 static_assert(std::is_const<T>::value, "");
3006 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
3007}
3008
3009// The `IsConvertible` classes here are needed because of the
3010// `std::is_convertible` bug in libcxx when compiled with GCC. This build
3011// configuration is used by Android NDK toolchain. Reference link:
3012// https://bugs.llvm.org/show_bug.cgi?id=27538.
3013template <typename From, typename To>
3015 static std::true_type testval(To);
3016 static std::false_type testval(...);
3017
3018 using type = decltype(testval(std::declval<From>()));
3019};
3020
3021template <typename From, typename To>
3022struct IsConvertible : IsConvertibleHelper<From, To>::type {};
3023
3024// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
3025// older version of libcxx is not supported.
3026template <typename From, typename To>
3027using EnableIfConvertibleToSpanConst =
3028 typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
3029} // namespace span_internal
3030
3031//------------------------------------------------------------------------------
3032// Span
3033//------------------------------------------------------------------------------
3034//
3035// A `Span` is an "array view" type for holding a view of a contiguous data
3036// array; the `Span` object does not and cannot own such data itself. A span
3037// provides an easy way to provide overloads for anything operating on
3038// contiguous sequences without needing to manage pointers and array lengths
3039// manually.
3040
3041// A span is conceptually a pointer (ptr) and a length (size) into an already
3042// existing array of contiguous memory; the array it represents references the
3043// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span`
3044// instead of raw pointers avoids many issues related to index out of bounds
3045// errors.
3046//
3047// Spans may also be constructed from containers holding contiguous sequences.
3048// Such containers must supply `data()` and `size() const` methods (e.g
3049// `std::vector<T>`, `phmap::InlinedVector<T, N>`). All implicit conversions to
3050// `phmap::Span` from such containers will create spans of type `const T`;
3051// spans which can mutate their values (of type `T`) must use explicit
3052// constructors.
3053//
3054// A `Span<T>` is somewhat analogous to an `phmap::string_view`, but for an array
3055// of elements of type `T`. A user of `Span` must ensure that the data being
3056// pointed to outlives the `Span` itself.
3057//
3058// You can construct a `Span<T>` in several ways:
3059//
3060// * Explicitly from a reference to a container type
3061// * Explicitly from a pointer and size
3062// * Implicitly from a container type (but only for spans of type `const T`)
3063// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.
3064//
3065// Examples:
3066//
3067// // Construct a Span explicitly from a container:
3068// std::vector<int> v = {1, 2, 3, 4, 5};
3069// auto span = phmap::Span<const int>(v);
3070//
3071// // Construct a Span explicitly from a C-style array:
3072// int a[5] = {1, 2, 3, 4, 5};
3073// auto span = phmap::Span<const int>(a);
3074//
3075// // Construct a Span implicitly from a container
3076// void MyRoutine(phmap::Span<const int> a) {
3077// ...
3078// }
3079// std::vector v = {1,2,3,4,5};
3080// MyRoutine(v) // convert to Span<const T>
3081//
3082// Note that `Span` objects, in addition to requiring that the memory they
3083// point to remains alive, must also ensure that such memory does not get
3084// reallocated. Therefore, to avoid undefined behavior, containers with
3085// associated span views should not invoke operations that may reallocate memory
3086// (such as resizing) or invalidate iterators into the container.
3087//
3088// One common use for a `Span` is when passing arguments to a routine that can
3089// accept a variety of array types (e.g. a `std::vector`, `phmap::InlinedVector`,
3090// a C-style array, etc.). Instead of creating overloads for each case, you
3091// can simply specify a `Span` as the argument to such a routine.
3092//
3093// Example:
3094//
3095// void MyRoutine(phmap::Span<const int> a) {
3096// ...
3097// }
3098//
3099// std::vector v = {1,2,3,4,5};
3100// MyRoutine(v);
3101//
3102// phmap::InlinedVector<int, 4> my_inline_vector;
3103// MyRoutine(my_inline_vector);
3104//
3105// // Explicit constructor from pointer,size
3106// int* my_array = new int[10];
3107// MyRoutine(phmap::Span<const int>(my_array, 10));
3108template <typename T>
3109class Span
3110{
3111private:
3112 // Used to determine whether a Span can be constructed from a container of
3113 // type C.
3114 template <typename C>
3115 using EnableIfConvertibleFrom =
3116 typename std::enable_if<span_internal::HasData<T, C>::value &&
3117 span_internal::HasSize<C>::value>::type;
3118
3119 // Used to SFINAE-enable a function when the slice elements are const.
3120 template <typename U>
3121 using EnableIfConstView =
3122 typename std::enable_if<std::is_const<T>::value, U>::type;
3123
3124 // Used to SFINAE-enable a function when the slice elements are mutable.
3125 template <typename U>
3126 using EnableIfMutableView =
3127 typename std::enable_if<!std::is_const<T>::value, U>::type;
3128
3129public:
3130 using value_type = phmap::remove_cv_t<T>;
3131 using pointer = T*;
3132 using const_pointer = const T*;
3133 using reference = T&;
3134 using const_reference = const T&;
3135 using iterator = pointer;
3136 using const_iterator = const_pointer;
3137 using reverse_iterator = std::reverse_iterator<iterator>;
3138 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
3139 using size_type = size_t;
3140 using difference_type = ptrdiff_t;
3141
3142 static const size_type npos = ~(size_type(0));
3143
3144 constexpr Span() noexcept : Span(nullptr, 0) {}
3145 constexpr Span(pointer array, size_type lgth) noexcept
3146 : ptr_(array), len_(lgth) {}
3147
3148 // Implicit conversion constructors
3149 template <size_t N>
3150 constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit)
3151 : Span(a, N) {}
3152
3153 // Explicit reference constructor for a mutable `Span<T>` type. Can be
3154 // replaced with MakeSpan() to infer the type parameter.
3155 template <typename V, typename = EnableIfConvertibleFrom<V>,
3156 typename = EnableIfMutableView<V>>
3157 explicit Span(V& v) noexcept // NOLINT(runtime/references)
3158 : Span(span_internal::GetData(v), v.size()) {}
3159
3160 // Implicit reference constructor for a read-only `Span<const T>` type
3161 template <typename V, typename = EnableIfConvertibleFrom<V>,
3162 typename = EnableIfConstView<V>>
3163 constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit)
3164 : Span(span_internal::GetData(v), v.size()) {}
3165
3166 // Implicit constructor from an initializer list, making it possible to pass a
3167 // brace-enclosed initializer list to a function expecting a `Span`. Such
3168 // spans constructed from an initializer list must be of type `Span<const T>`.
3169 //
3170 // void Process(phmap::Span<const int> x);
3171 // Process({1, 2, 3});
3172 //
3173 // Note that as always the array referenced by the span must outlive the span.
3174 // Since an initializer list constructor acts as if it is fed a temporary
3175 // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this
3176 // constructor only when the `std::initializer_list` itself outlives the span.
3177 // In order to meet this requirement it's sufficient to ensure that neither
3178 // the span nor a copy of it is used outside of the expression in which it's
3179 // created:
3180 //
3181 // // Assume that this function uses the array directly, not retaining any
3182 // // copy of the span or pointer to any of its elements.
3183 // void Process(phmap::Span<const int> ints);
3184 //
3185 // // Okay: the std::initializer_list<int> will reference a temporary array
3186 // // that isn't destroyed until after the call to Process returns.
3187 // Process({ 17, 19 });
3188 //
3189 // // Not okay: the storage used by the std::initializer_list<int> is not
3190 // // allowed to be referenced after the first line.
3191 // phmap::Span<const int> ints = { 17, 19 };
3192 // Process(ints);
3193 //
3194 // // Not okay for the same reason as above: even when the elements of the
3195 // // initializer list expression are not temporaries the underlying array
3196 // // is, so the initializer list must still outlive the span.
3197 // const int foo = 17;
3198 // phmap::Span<const int> ints = { foo };
3199 // Process(ints);
3200 //
3201 template <typename LazyT = T,
3202 typename = EnableIfConstView<LazyT>>
3203 Span(
3204 std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit)
3205 : Span(v.begin(), v.size()) {}
3206
3207 // Accessors
3208
3209 // Span::data()
3210 //
3211 // Returns a pointer to the span's underlying array of data (which is held
3212 // outside the span).
3213 constexpr pointer data() const noexcept { return ptr_; }
3214
3215 // Span::size()
3216 //
3217 // Returns the size of this span.
3218 constexpr size_type size() const noexcept { return len_; }
3219
3220 // Span::length()
3221 //
3222 // Returns the length (size) of this span.
3223 constexpr size_type length() const noexcept { return size(); }
3224
3225 // Span::empty()
3226 //
3227 // Returns a boolean indicating whether or not this span is considered empty.
3228 constexpr bool empty() const noexcept { return size() == 0; }
3229
3230 // Span::operator[]
3231 //
3232 // Returns a reference to the i'th element of this span.
3233 constexpr reference operator[](size_type i) const noexcept {
3234 // MSVC 2015 accepts this as constexpr, but not ptr_[i]
3235 return *(data() + i);
3236 }
3237
3238 // Span::at()
3239 //
3240 // Returns a reference to the i'th element of this span.
3241 constexpr reference at(size_type i) const {
3242 return PHMAP_PREDICT_TRUE(i < size()) //
3243 ? *(data() + i)
3244 : (base_internal::ThrowStdOutOfRange(
3245 "Span::at failed bounds check"),
3246 *(data() + i));
3247 }
3248
3249 // Span::front()
3250 //
3251 // Returns a reference to the first element of this span.
3252 constexpr reference front() const noexcept {
3253 return PHMAP_ASSERT(size() > 0), *data();
3254 }
3255
3256 // Span::back()
3257 //
3258 // Returns a reference to the last element of this span.
3259 constexpr reference back() const noexcept {
3260 return PHMAP_ASSERT(size() > 0), *(data() + size() - 1);
3261 }
3262
3263 // Span::begin()
3264 //
3265 // Returns an iterator to the first element of this span.
3266 constexpr iterator begin() const noexcept { return data(); }
3267
3268 // Span::cbegin()
3269 //
3270 // Returns a const iterator to the first element of this span.
3271 constexpr const_iterator cbegin() const noexcept { return begin(); }
3272
3273 // Span::end()
3274 //
3275 // Returns an iterator to the last element of this span.
3276 constexpr iterator end() const noexcept { return data() + size(); }
3277
3278 // Span::cend()
3279 //
3280 // Returns a const iterator to the last element of this span.
3281 constexpr const_iterator cend() const noexcept { return end(); }
3282
3283 // Span::rbegin()
3284 //
3285 // Returns a reverse iterator starting at the last element of this span.
3286 constexpr reverse_iterator rbegin() const noexcept {
3287 return reverse_iterator(end());
3288 }
3289
3290 // Span::crbegin()
3291 //
3292 // Returns a reverse const iterator starting at the last element of this span.
3293 constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
3294
3295 // Span::rend()
3296 //
3297 // Returns a reverse iterator starting at the first element of this span.
3298 constexpr reverse_iterator rend() const noexcept {
3299 return reverse_iterator(begin());
3300 }
3301
3302 // Span::crend()
3303 //
3304 // Returns a reverse iterator starting at the first element of this span.
3305 constexpr const_reverse_iterator crend() const noexcept { return rend(); }
3306
3307 // Span mutations
3308
3309 // Span::remove_prefix()
3310 //
3311 // Removes the first `n` elements from the span.
3312 void remove_prefix(size_type n) noexcept {
3313 assert(size() >= n);
3314 ptr_ += n;
3315 len_ -= n;
3316 }
3317
3318 // Span::remove_suffix()
3319 //
3320 // Removes the last `n` elements from the span.
3321 void remove_suffix(size_type n) noexcept {
3322 assert(size() >= n);
3323 len_ -= n;
3324 }
3325
3326 // Span::subspan()
3327 //
3328 // Returns a `Span` starting at element `pos` and of length `len`. Both `pos`
3329 // and `len` are of type `size_type` and thus non-negative. Parameter `pos`
3330 // must be <= size(). Any `len` value that points past the end of the span
3331 // will be trimmed to at most size() - `pos`. A default `len` value of `npos`
3332 // ensures the returned subspan continues until the end of the span.
3333 //
3334 // Examples:
3335 //
3336 // std::vector<int> vec = {10, 11, 12, 13};
3337 // phmap::MakeSpan(vec).subspan(1, 2); // {11, 12}
3338 // phmap::MakeSpan(vec).subspan(2, 8); // {12, 13}
3339 // phmap::MakeSpan(vec).subspan(1); // {11, 12, 13}
3340 // phmap::MakeSpan(vec).subspan(4); // {}
3341 // phmap::MakeSpan(vec).subspan(5); // throws std::out_of_range
3342 constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
3343 return (pos <= size())
3344 ? Span(data() + pos, span_internal::Min(size() - pos, len))
3345 : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
3346 }
3347
3348 // Span::first()
3349 //
3350 // Returns a `Span` containing first `len` elements. Parameter `len` is of
3351 // type `size_type` and thus non-negative. `len` value must be <= size().
3352 //
3353 // Examples:
3354 //
3355 // std::vector<int> vec = {10, 11, 12, 13};
3356 // phmap::MakeSpan(vec).first(1); // {10}
3357 // phmap::MakeSpan(vec).first(3); // {10, 11, 12}
3358 // phmap::MakeSpan(vec).first(5); // throws std::out_of_range
3359 constexpr Span first(size_type len) const {
3360 return (len <= size())
3361 ? Span(data(), len)
3362 : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
3363 }
3364
3365 // Span::last()
3366 //
3367 // Returns a `Span` containing last `len` elements. Parameter `len` is of
3368 // type `size_type` and thus non-negative. `len` value must be <= size().
3369 //
3370 // Examples:
3371 //
3372 // std::vector<int> vec = {10, 11, 12, 13};
3373 // phmap::MakeSpan(vec).last(1); // {13}
3374 // phmap::MakeSpan(vec).last(3); // {11, 12, 13}
3375 // phmap::MakeSpan(vec).last(5); // throws std::out_of_range
3376 constexpr Span last(size_type len) const {
3377 return (len <= size())
3378 ? Span(size() - len + data(), len)
3379 : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
3380 }
3381
3382 // Support for phmap::Hash.
3383 template <typename H>
3384 friend H AbslHashValue(H h, Span v) {
3385 return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
3386 v.size());
3387 }
3388
3389private:
3390 pointer ptr_;
3391 size_type len_;
3392};
3393
3394template <typename T>
3395const typename Span<T>::size_type Span<T>::npos;
3396
3397// Span relationals
3398
3399// Equality is compared element-by-element, while ordering is lexicographical.
3400// We provide three overloads for each operator to cover any combination on the
3401// left or right hand side of mutable Span<T>, read-only Span<const T>, and
3402// convertible-to-read-only Span<T>.
3403// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering
3404// template functions, 5 overloads per operator is needed as a workaround. We
3405// should update them to 3 overloads per operator using non-deduced context like
3406// string_view, i.e.
3407// - (Span<T>, Span<T>)
3408// - (Span<T>, non_deduced<Span<const T>>)
3409// - (non_deduced<Span<const T>>, Span<T>)
3410
3411// operator==
3412template <typename T>
3413bool operator==(Span<T> a, Span<T> b) {
3414 return span_internal::EqualImpl<const T>(a, b);
3415}
3416
3417template <typename T>
3418bool operator==(Span<const T> a, Span<T> b) {
3419 return span_internal::EqualImpl<const T>(a, b);
3420}
3421
3422template <typename T>
3423bool operator==(Span<T> a, Span<const T> b) {
3424 return span_internal::EqualImpl<const T>(a, b);
3425}
3426
3427template <typename T, typename U,
3428 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3429bool operator==(const U& a, Span<T> b) {
3430 return span_internal::EqualImpl<const T>(a, b);
3431}
3432
3433template <typename T, typename U,
3434 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3435bool operator==(Span<T> a, const U& b) {
3436 return span_internal::EqualImpl<const T>(a, b);
3437}
3438
3439// operator!=
3440template <typename T>
3441bool operator!=(Span<T> a, Span<T> b) {
3442 return !(a == b);
3443}
3444
3445template <typename T>
3446bool operator!=(Span<const T> a, Span<T> b) {
3447 return !(a == b);
3448}
3449
3450template <typename T>
3451bool operator!=(Span<T> a, Span<const T> b) {
3452 return !(a == b);
3453}
3454
3455template <typename T, typename U,
3456 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3457bool operator!=(const U& a, Span<T> b) {
3458 return !(a == b);
3459}
3460
3461template <typename T, typename U,
3462 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3463bool operator!=(Span<T> a, const U& b) {
3464 return !(a == b);
3465}
3466
3467// operator<
3468template <typename T>
3469bool operator<(Span<T> a, Span<T> b) {
3470 return span_internal::LessThanImpl<const T>(a, b);
3471}
3472
3473template <typename T>
3474bool operator<(Span<const T> a, Span<T> b) {
3475 return span_internal::LessThanImpl<const T>(a, b);
3476}
3477
3478template <typename T>
3479bool operator<(Span<T> a, Span<const T> b) {
3480 return span_internal::LessThanImpl<const T>(a, b);
3481}
3482
3483template <typename T, typename U,
3484 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3485bool operator<(const U& a, Span<T> b) {
3486 return span_internal::LessThanImpl<const T>(a, b);
3487}
3488
3489template <typename T, typename U,
3490 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3491bool operator<(Span<T> a, const U& b) {
3492 return span_internal::LessThanImpl<const T>(a, b);
3493}
3494
3495// operator>
3496template <typename T>
3497bool operator>(Span<T> a, Span<T> b) {
3498 return b < a;
3499}
3500
3501template <typename T>
3502bool operator>(Span<const T> a, Span<T> b) {
3503 return b < a;
3504}
3505
3506template <typename T>
3507bool operator>(Span<T> a, Span<const T> b) {
3508 return b < a;
3509}
3510
3511template <typename T, typename U,
3512 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3513bool operator>(const U& a, Span<T> b) {
3514 return b < a;
3515}
3516
3517template <typename T, typename U,
3518 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3519bool operator>(Span<T> a, const U& b) {
3520 return b < a;
3521}
3522
3523// operator<=
3524template <typename T>
3525bool operator<=(Span<T> a, Span<T> b) {
3526 return !(b < a);
3527}
3528
3529template <typename T>
3530bool operator<=(Span<const T> a, Span<T> b) {
3531 return !(b < a);
3532}
3533
3534template <typename T>
3535bool operator<=(Span<T> a, Span<const T> b) {
3536 return !(b < a);
3537}
3538
3539template <typename T, typename U,
3540 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3541bool operator<=(const U& a, Span<T> b) {
3542 return !(b < a);
3543}
3544
3545template <typename T, typename U,
3546 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3547bool operator<=(Span<T> a, const U& b) {
3548 return !(b < a);
3549}
3550
3551// operator>=
3552template <typename T>
3553bool operator>=(Span<T> a, Span<T> b) {
3554 return !(a < b);
3555}
3556
3557template <typename T>
3558bool operator>=(Span<const T> a, Span<T> b) {
3559 return !(a < b);
3560}
3561
3562template <typename T>
3563bool operator>=(Span<T> a, Span<const T> b) {
3564 return !(a < b);
3565}
3566
3567template <typename T, typename U,
3568 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3569bool operator>=(const U& a, Span<T> b) {
3570 return !(a < b);
3571}
3572
3573template <typename T, typename U,
3574 typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
3575bool operator>=(Span<T> a, const U& b) {
3576 return !(a < b);
3577}
3578
3579// MakeSpan()
3580//
3581// Constructs a mutable `Span<T>`, deducing `T` automatically from either a
3582// container or pointer+size.
3583//
3584// Because a read-only `Span<const T>` is implicitly constructed from container
3585// types regardless of whether the container itself is a const container,
3586// constructing mutable spans of type `Span<T>` from containers requires
3587// explicit constructors. The container-accepting version of `MakeSpan()`
3588// deduces the type of `T` by the constness of the pointer received from the
3589// container's `data()` member. Similarly, the pointer-accepting version returns
3590// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.
3591//
3592// Examples:
3593//
3594// void MyRoutine(phmap::Span<MyComplicatedType> a) {
3595// ...
3596// };
3597// // my_vector is a container of non-const types
3598// std::vector<MyComplicatedType> my_vector;
3599//
3600// // Constructing a Span implicitly attempts to create a Span of type
3601// // `Span<const T>`
3602// MyRoutine(my_vector); // error, type mismatch
3603//
3604// // Explicitly constructing the Span is verbose
3605// MyRoutine(phmap::Span<MyComplicatedType>(my_vector));
3606//
3607// // Use MakeSpan() to make an phmap::Span<T>
3608// MyRoutine(phmap::MakeSpan(my_vector));
3609//
3610// // Construct a span from an array ptr+size
3611// phmap::Span<T> my_span() {
3612// return phmap::MakeSpan(&array[0], num_elements_);
3613// }
3614//
3615template <int&... ExplicitArgumentBarrier, typename T>
3616constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept {
3617 return Span<T>(ptr, size);
3618}
3619
3620template <int&... ExplicitArgumentBarrier, typename T>
3621Span<T> MakeSpan(T* begin, T* end) noexcept {
3622 return PHMAP_ASSERT(begin <= end), Span<T>(begin, end - begin);
3623}
3624
3625template <int&... ExplicitArgumentBarrier, typename C>
3626constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references)
3627 -> decltype(phmap::MakeSpan(span_internal::GetData(c), c.size())) {
3628 return MakeSpan(span_internal::GetData(c), c.size());
3629}
3630
3631template <int&... ExplicitArgumentBarrier, typename T, size_t N>
3632constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
3633 return Span<T>(array, N);
3634}
3635
3636// MakeConstSpan()
3637//
3638// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,
3639// but always returning a `Span<const T>`.
3640//
3641// Examples:
3642//
3643// void ProcessInts(phmap::Span<const int> some_ints);
3644//
3645// // Call with a pointer and size.
3646// int array[3] = { 0, 0, 0 };
3647// ProcessInts(phmap::MakeConstSpan(&array[0], 3));
3648//
3649// // Call with a [begin, end) pair.
3650// ProcessInts(phmap::MakeConstSpan(&array[0], &array[3]));
3651//
3652// // Call directly with an array.
3653// ProcessInts(phmap::MakeConstSpan(array));
3654//
3655// // Call with a contiguous container.
3656// std::vector<int> some_ints = ...;
3657// ProcessInts(phmap::MakeConstSpan(some_ints));
3658// ProcessInts(phmap::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
3659//
3660template <int&... ExplicitArgumentBarrier, typename T>
3661constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept {
3662 return Span<const T>(ptr, size);
3663}
3664
3665template <int&... ExplicitArgumentBarrier, typename T>
3666Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
3667 return PHMAP_ASSERT(begin <= end), Span<const T>(begin, end - begin);
3668}
3669
3670template <int&... ExplicitArgumentBarrier, typename C>
3671constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) {
3672 return MakeSpan(c);
3673}
3674
3675template <int&... ExplicitArgumentBarrier, typename T, size_t N>
3676constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
3677 return Span<const T>(array, N);
3678}
3679} // namespace phmap
3680
3681// ---------------------------------------------------------------------------
3682// layout.h
3683// ---------------------------------------------------------------------------
3684#if defined(__GXX_RTTI)
3685 #define PHMAP_INTERNAL_HAS_CXA_DEMANGLE
3686#endif
3687
3688#ifdef PHMAP_INTERNAL_HAS_CXA_DEMANGLE
3689 #include <cxxabi.h>
3690#endif
3691
3692namespace phmap {
3693namespace priv {
3694
3695// A type wrapper that instructs `Layout` to use the specific alignment for the
3696// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
3697// and behavior as `Layout<..., T, ...>` except that the first element of the
3698// array of `T` is aligned to `N` (the rest of the elements follow without
3699// padding).
3700//
3701// Requires: `N >= alignof(T)` and `N` is a power of 2.
3702template <class T, size_t N>
3703struct Aligned;
3704
3705namespace internal_layout {
3706
3707template <class T>
3708struct NotAligned {};
3709
3710template <class T, size_t N>
3711struct NotAligned<const Aligned<T, N>> {
3712 static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified");
3713};
3714
3715template <size_t>
3716using IntToSize = size_t;
3717
3718template <class>
3719using TypeToSize = size_t;
3720
3721template <class T>
3722struct Type : NotAligned<T> {
3723 using type = T;
3724};
3725
3726template <class T, size_t N>
3727struct Type<Aligned<T, N>> {
3728 using type = T;
3729};
3730
3731template <class T>
3732struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
3733
3734template <class T, size_t N>
3735struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
3736
3737// Note: workaround for https://gcc.gnu.org/PR88115
3738template <class T>
3739struct AlignOf : NotAligned<T> {
3740 static constexpr size_t value = alignof(T);
3741};
3742
3743template <class T, size_t N>
3744struct AlignOf<Aligned<T, N>> {
3745 static_assert(N % alignof(T) == 0,
3746 "Custom alignment can't be lower than the type's alignment");
3747 static constexpr size_t value = N;
3748};
3749
3750// Does `Ts...` contain `T`?
3751template <class T, class... Ts>
3752using Contains = phmap::disjunction<std::is_same<T, Ts>...>;
3753
3754template <class From, class To>
3755using CopyConst =
3756 typename std::conditional<std::is_const<From>::value, const To, To>::type;
3757
3758// Note: We're not qualifying this with phmap:: because it doesn't compile under
3759// MSVC.
3760template <class T>
3761using SliceType = Span<T>;
3762
3763// This namespace contains no types. It prevents functions defined in it from
3764// being found by ADL.
3765namespace adl_barrier {
3766
3767template <class Needle, class... Ts>
3768constexpr size_t Find(Needle, Needle, Ts...) {
3769 static_assert(!Contains<Needle, Ts...>(), "Duplicate element type");
3770 return 0;
3771}
3772
3773template <class Needle, class T, class... Ts>
3774constexpr size_t Find(Needle, T, Ts...) {
3775 return adl_barrier::Find(Needle(), Ts()...) + 1;
3776}
3777
3778constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }
3779
3780// Returns `q * m` for the smallest `q` such that `q * m >= n`.
3781// Requires: `m` is a power of two. It's enforced by IsLegalElementType below.
3782constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }
3783
3784constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }
3785
3786constexpr size_t Max(size_t a) { return a; }
3787
3788template <class... Ts>
3789constexpr size_t Max(size_t a, size_t b, Ts... rest) {
3790 return adl_barrier::Max(b < a ? a : b, rest...);
3791}
3792
3793} // namespace adl_barrier
3794
3795template <bool C>
3796using EnableIf = typename std::enable_if<C, int>::type;
3797
3798// Can `T` be a template argument of `Layout`?
3799// ---------------------------------------------------------------------------
3800template <class T>
3801using IsLegalElementType = std::integral_constant<
3802 bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
3803 !std::is_reference<typename Type<T>::type>::value &&
3804 !std::is_volatile<typename Type<T>::type>::value &&
3805 adl_barrier::IsPow2(AlignOf<T>::value)>;
3806
3807template <class Elements, class SizeSeq, class OffsetSeq>
3808class LayoutImpl;
3809
3810// ---------------------------------------------------------------------------
3811// Public base class of `Layout` and the result type of `Layout::Partial()`.
3812//
3813// `Elements...` contains all template arguments of `Layout` that created this
3814// instance.
3815//
3816// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is the number of arguments
3817// passed to `Layout::Partial()` or `Layout::Layout()`.
3818//
3819// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is
3820// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we
3821// can compute offsets).
3822// ---------------------------------------------------------------------------
3823template <class... Elements, size_t... SizeSeq, size_t... OffsetSeq>
3824class LayoutImpl<std::tuple<Elements...>, phmap::index_sequence<SizeSeq...>,
3825 phmap::index_sequence<OffsetSeq...>>
3826{
3827private:
3828 static_assert(sizeof...(Elements) > 0, "At least one field is required");
3829 static_assert(phmap::conjunction<IsLegalElementType<Elements>...>::value,
3830 "Invalid element type (see IsLegalElementType)");
3831
3832 enum {
3833 NumTypes = sizeof...(Elements),
3834 NumSizes = sizeof...(SizeSeq),
3835 NumOffsets = sizeof...(OffsetSeq),
3836 };
3837
3838 // These are guaranteed by `Layout`.
3839 static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
3840 "Internal error");
3841 static_assert(NumTypes > 0, "Internal error");
3842
3843 // Returns the index of `T` in `Elements...`. Results in a compilation error
3844 // if `Elements...` doesn't contain exactly one instance of `T`.
3845 template <class T>
3846 static constexpr size_t ElementIndex() {
3847 static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),
3848 "Type not found");
3849 return adl_barrier::Find(Type<T>(),
3850 Type<typename Type<Elements>::type>()...);
3851 }
3852
3853 template <size_t N>
3854 using ElementAlignment =
3855 AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;
3856
3857public:
3858 // Element types of all arrays packed in a tuple.
3859 using ElementTypes = std::tuple<typename Type<Elements>::type...>;
3860
3861 // Element type of the Nth array.
3862 template <size_t N>
3863 using ElementType = typename std::tuple_element<N, ElementTypes>::type;
3864
3865 constexpr explicit LayoutImpl(IntToSize<SizeSeq>... sizes)
3866 : size_{sizes...} {}
3867
3868 // Alignment of the layout, equal to the strictest alignment of all elements.
3869 // All pointers passed to the methods of layout must be aligned to this value.
3870 static constexpr size_t Alignment() {
3871 return adl_barrier::Max(AlignOf<Elements>::value...);
3872 }
3873
3874 // Offset in bytes of the Nth array.
3875 //
3876 // // int[3], 4 bytes of padding, double[4].
3877 // Layout<int, double> x(3, 4);
3878 // assert(x.Offset<0>() == 0); // The ints starts from 0.
3879 // assert(x.Offset<1>() == 16); // The doubles starts from 16.
3880 //
3881 // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
3882 template <size_t N, EnableIf<N == 0> = 0>
3883 constexpr size_t Offset() const {
3884 return 0;
3885 }
3886
3887 template <size_t N, EnableIf<N != 0> = 0>
3888 constexpr size_t Offset() const {
3889 static_assert(N < NumOffsets, "Index out of bounds");
3890 return adl_barrier::Align(
3891 Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
3892 ElementAlignment<N>::value);
3893 }
3894
3895 // Offset in bytes of the array with the specified element type. There must
3896 // be exactly one such array and its zero-based index must be at most
3897 // `NumSizes`.
3898 //
3899 // // int[3], 4 bytes of padding, double[4].
3900 // Layout<int, double> x(3, 4);
3901 // assert(x.Offset<int>() == 0); // The ints starts from 0.
3902 // assert(x.Offset<double>() == 16); // The doubles starts from 16.
3903 template <class T>
3904 constexpr size_t Offset() const {
3905 return Offset<ElementIndex<T>()>();
3906 }
3907
3908 // Offsets in bytes of all arrays for which the offsets are known.
3909 constexpr std::array<size_t, NumOffsets> Offsets() const {
3910 return {{Offset<OffsetSeq>()...}};
3911 }
3912
3913 // The number of elements in the Nth array. This is the Nth argument of
3914 // `Layout::Partial()` or `Layout::Layout()` (zero-based).
3915 //
3916 // // int[3], 4 bytes of padding, double[4].
3917 // Layout<int, double> x(3, 4);
3918 // assert(x.Size<0>() == 3);
3919 // assert(x.Size<1>() == 4);
3920 //
3921 // Requires: `N < NumSizes`.
3922 template <size_t N>
3923 constexpr size_t Size() const {
3924 static_assert(N < NumSizes, "Index out of bounds");
3925 return size_[N];
3926 }
3927
3928 // The number of elements in the array with the specified element type.
3929 // There must be exactly one such array and its zero-based index must be
3930 // at most `NumSizes`.
3931 //
3932 // // int[3], 4 bytes of padding, double[4].
3933 // Layout<int, double> x(3, 4);
3934 // assert(x.Size<int>() == 3);
3935 // assert(x.Size<double>() == 4);
3936 template <class T>
3937 constexpr size_t Size() const {
3938 return Size<ElementIndex<T>()>();
3939 }
3940
3941 // The number of elements of all arrays for which they are known.
3942 constexpr std::array<size_t, NumSizes> Sizes() const {
3943 return {{Size<SizeSeq>()...}};
3944 }
3945
3946 // Pointer to the beginning of the Nth array.
3947 //
3948 // `Char` must be `[const] [signed|unsigned] char`.
3949 //
3950 // // int[3], 4 bytes of padding, double[4].
3951 // Layout<int, double> x(3, 4);
3952 // unsigned char* p = new unsigned char[x.AllocSize()];
3953 // int* ints = x.Pointer<0>(p);
3954 // double* doubles = x.Pointer<1>(p);
3955 //
3956 // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
3957 // Requires: `p` is aligned to `Alignment()`.
3958 template <size_t N, class Char>
3959 CopyConst<Char, ElementType<N>>* Pointer(Char* p) const {
3960 using C = typename std::remove_const<Char>::type;
3961 static_assert(
3962 std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
3963 std::is_same<C, signed char>(),
3964 "The argument must be a pointer to [const] [signed|unsigned] char");
3965 constexpr size_t alignment = Alignment();
3966 (void)alignment;
3967 assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
3968 return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());
3969 }
3970
3971 // Pointer to the beginning of the array with the specified element type.
3972 // There must be exactly one such array and its zero-based index must be at
3973 // most `NumSizes`.
3974 //
3975 // `Char` must be `[const] [signed|unsigned] char`.
3976 //
3977 // // int[3], 4 bytes of padding, double[4].
3978 // Layout<int, double> x(3, 4);
3979 // unsigned char* p = new unsigned char[x.AllocSize()];
3980 // int* ints = x.Pointer<int>(p);
3981 // double* doubles = x.Pointer<double>(p);
3982 //
3983 // Requires: `p` is aligned to `Alignment()`.
3984 template <class T, class Char>
3985 CopyConst<Char, T>* Pointer(Char* p) const {
3986 return Pointer<ElementIndex<T>()>(p);
3987 }
3988
3989 // Pointers to all arrays for which pointers are known.
3990 //
3991 // `Char` must be `[const] [signed|unsigned] char`.
3992 //
3993 // // int[3], 4 bytes of padding, double[4].
3994 // Layout<int, double> x(3, 4);
3995 // unsigned char* p = new unsigned char[x.AllocSize()];
3996 //
3997 // int* ints;
3998 // double* doubles;
3999 // std::tie(ints, doubles) = x.Pointers(p);
4000 //
4001 // Requires: `p` is aligned to `Alignment()`.
4002 //
4003 // Note: We're not using ElementType alias here because it does not compile
4004 // under MSVC.
4005 template <class Char>
4006 std::tuple<CopyConst<
4007 Char, typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...>
4008 Pointers(Char* p) const {
4009 return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
4010 Pointer<OffsetSeq>(p)...);
4011 }
4012
4013 // The Nth array.
4014 //
4015 // `Char` must be `[const] [signed|unsigned] char`.
4016 //
4017 // // int[3], 4 bytes of padding, double[4].
4018 // Layout<int, double> x(3, 4);
4019 // unsigned char* p = new unsigned char[x.AllocSize()];
4020 // Span<int> ints = x.Slice<0>(p);
4021 // Span<double> doubles = x.Slice<1>(p);
4022 //
4023 // Requires: `N < NumSizes`.
4024 // Requires: `p` is aligned to `Alignment()`.
4025 template <size_t N, class Char>
4026 SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const {
4027 return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
4028 }
4029
4030 // The array with the specified element type. There must be exactly one
4031 // such array and its zero-based index must be less than `NumSizes`.
4032 //
4033 // `Char` must be `[const] [signed|unsigned] char`.
4034 //
4035 // // int[3], 4 bytes of padding, double[4].
4036 // Layout<int, double> x(3, 4);
4037 // unsigned char* p = new unsigned char[x.AllocSize()];
4038 // Span<int> ints = x.Slice<int>(p);
4039 // Span<double> doubles = x.Slice<double>(p);
4040 //
4041 // Requires: `p` is aligned to `Alignment()`.
4042 template <class T, class Char>
4043 SliceType<CopyConst<Char, T>> Slice(Char* p) const {
4044 return Slice<ElementIndex<T>()>(p);
4045 }
4046
4047 // All arrays with known sizes.
4048 //
4049 // `Char` must be `[const] [signed|unsigned] char`.
4050 //
4051 // // int[3], 4 bytes of padding, double[4].
4052 // Layout<int, double> x(3, 4);
4053 // unsigned char* p = new unsigned char[x.AllocSize()];
4054 //
4055 // Span<int> ints;
4056 // Span<double> doubles;
4057 // std::tie(ints, doubles) = x.Slices(p);
4058 //
4059 // Requires: `p` is aligned to `Alignment()`.
4060 //
4061 // Note: We're not using ElementType alias here because it does not compile
4062 // under MSVC.
4063 template <class Char>
4064 std::tuple<SliceType<CopyConst<
4065 Char, typename std::tuple_element<SizeSeq, ElementTypes>::type>>...>
4066 Slices(Char* p) const {
4067 // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63875 (fixed
4068 // in 6.1).
4069 (void)p;
4070 return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
4071 Slice<SizeSeq>(p)...);
4072 }
4073
4074 // The size of the allocation that fits all arrays.
4075 //
4076 // // int[3], 4 bytes of padding, double[4].
4077 // Layout<int, double> x(3, 4);
4078 // unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes
4079 //
4080 // Requires: `NumSizes == sizeof...(Ts)`.
4081 constexpr size_t AllocSize() const {
4082 static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
4083 return Offset<NumTypes - 1>() +
4084 SizeOf<ElementType<NumTypes - 1>>() * size_[NumTypes - 1];
4085 }
4086
4087 // If built with --config=asan, poisons padding bytes (if any) in the
4088 // allocation. The pointer must point to a memory block at least
4089 // `AllocSize()` bytes in length.
4090 //
4091 // `Char` must be `[const] [signed|unsigned] char`.
4092 //
4093 // Requires: `p` is aligned to `Alignment()`.
4094 template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
4095 void PoisonPadding(const Char* p) const {
4096 Pointer<0>(p); // verify the requirements on `Char` and `p`
4097 }
4098
4099 template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
4100 void PoisonPadding(const Char* p) const {
4101 static_assert(N < NumOffsets, "Index out of bounds");
4102 (void)p;
4103#ifdef ADDRESS_SANITIZER
4104 PoisonPadding<Char, N - 1>(p);
4105 // The `if` is an optimization. It doesn't affect the observable behaviour.
4106 if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
4107 size_t start =
4108 Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1];
4109 ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
4110 }
4111#endif
4112 }
4113
4114private:
4115 // Arguments of `Layout::Partial()` or `Layout::Layout()`.
4116 size_t size_[NumSizes > 0 ? NumSizes : 1];
4117};
4118
4119template <size_t NumSizes, class... Ts>
4120using LayoutType = LayoutImpl<
4121 std::tuple<Ts...>, phmap::make_index_sequence<NumSizes>,
4122 phmap::make_index_sequence<adl_barrier::Min(sizeof...(Ts), NumSizes + 1)>>;
4123
4124} // namespace internal_layout
4125
4126// ---------------------------------------------------------------------------
4127// Descriptor of arrays of various types and sizes laid out in memory one after
4128// another. See the top of the file for documentation.
4129//
4130// Check out the public API of internal_layout::LayoutImpl above. The type is
4131// internal to the library but its methods are public, and they are inherited
4132// by `Layout`.
4133// ---------------------------------------------------------------------------
4134template <class... Ts>
4135class Layout : public internal_layout::LayoutType<sizeof...(Ts), Ts...>
4136{
4137public:
4138 static_assert(sizeof...(Ts) > 0, "At least one field is required");
4139 static_assert(
4141 "Invalid element type (see IsLegalElementType)");
4142
4143 template <size_t NumSizes>
4144 using PartialType = internal_layout::LayoutType<NumSizes, Ts...>;
4145
4146 template <class... Sizes>
4147 static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {
4148 static_assert(sizeof...(Sizes) <= sizeof...(Ts), "");
4149 return PartialType<sizeof...(Sizes)>(phmap::forward<Sizes>(sizes)...);
4150 }
4151
4152 // Creates a layout with the sizes of all arrays specified. If you know
4153 // only the sizes of the first N arrays (where N can be zero), you can use
4154 // `Partial()` defined above. The constructor is essentially equivalent to
4155 // calling `Partial()` and passing in all array sizes; the constructor is
4156 // provided as a convenient abbreviation.
4157 //
4158 // Note: The sizes of the arrays must be specified in number of elements,
4159 // not in bytes.
4160 constexpr explicit Layout(internal_layout::TypeToSize<Ts>... sizes)
4161 : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {}
4162};
4163
4164} // namespace priv
4165} // namespace phmap
4166
4167// ---------------------------------------------------------------------------
4168// compressed_tuple.h
4169// ---------------------------------------------------------------------------
4170
4171#ifdef _MSC_VER
4172 // We need to mark these classes with this declspec to ensure that
4173 // CompressedTuple happens.
4174 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
4175#else // _MSC_VER
4176 #define PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
4177#endif // _MSC_VER
4178
4179namespace phmap {
4180namespace priv {
4181
4182template <typename... Ts>
4183class CompressedTuple;
4184
4185namespace internal_compressed_tuple {
4186
4187template <typename D, size_t I>
4188struct Elem;
4189template <typename... B, size_t I>
4190struct Elem<CompressedTuple<B...>, I>
4191 : std::tuple_element<I, std::tuple<B...>> {};
4192template <typename D, size_t I>
4193using ElemT = typename Elem<D, I>::type;
4194
4195// ---------------------------------------------------------------------------
4196// Use the __is_final intrinsic if available. Where it's not available, classes
4197// declared with the 'final' specifier cannot be used as CompressedTuple
4198// elements.
4199// TODO(sbenza): Replace this with std::is_final in C++14.
4200// ---------------------------------------------------------------------------
4201template <typename T>
4202constexpr bool IsFinal() {
4203#if defined(__clang__) || defined(__GNUC__)
4204 return __is_final(T);
4205#else
4206 return false;
4207#endif
4208}
4209
4210template <typename T>
4211constexpr bool ShouldUseBase() {
4212#ifdef __INTEL_COMPILER
4213 // avoid crash in Intel compiler
4214 // assertion failed at: "shared/cfe/edgcpfe/lower_init.c", line 7013
4215 return false;
4216#else
4217 return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
4218#endif
4219}
4220
4221// The storage class provides two specializations:
4222// - For empty classes, it stores T as a base class.
4223// - For everything else, it stores T as a member.
4224// ------------------------------------------------
4225template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
4226struct Storage
4227{
4228 using T = ElemT<D, I>;
4229 T value;
4230 constexpr Storage() = default;
4231 explicit constexpr Storage(T&& v) : value(phmap::forward<T>(v)) {}
4232 constexpr const T& get() const& { return value; }
4233 T& get() & { return value; }
4234 constexpr const T&& get() const&& { return phmap::move(*this).value; }
4235 T&& get() && { return std::move(*this).value; }
4236};
4237
4238template <typename D, size_t I>
4239struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true>
4240 : ElemT<D, I>
4241{
4242 using T = internal_compressed_tuple::ElemT<D, I>;
4243 constexpr Storage() = default;
4244 explicit constexpr Storage(T&& v) : T(phmap::forward<T>(v)) {}
4245 constexpr const T& get() const& { return *this; }
4246 T& get() & { return *this; }
4247 constexpr const T&& get() const&& { return phmap::move(*this); }
4248 T&& get() && { return std::move(*this); }
4249};
4250
4251template <typename D, typename I>
4252struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
4253
4254template <typename... Ts, size_t... I>
4255struct PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
4256 CompressedTupleImpl<CompressedTuple<Ts...>, phmap::index_sequence<I...>>
4257 // We use the dummy identity function through std::integral_constant to
4258 // convince MSVC of accepting and expanding I in that context. Without it
4259 // you would get:
4260 // error C3548: 'I': parameter pack cannot be used in this context
4261 : Storage<CompressedTuple<Ts...>,
4262 std::integral_constant<size_t, I>::value>...
4263{
4264 constexpr CompressedTupleImpl() = default;
4265 explicit constexpr CompressedTupleImpl(Ts&&... args)
4266 : Storage<CompressedTuple<Ts...>, I>(phmap::forward<Ts>(args))... {}
4267};
4268
4269} // namespace internal_compressed_tuple
4270
4271// ---------------------------------------------------------------------------
4272// Helper class to perform the Empty Base Class Optimization.
4273// Ts can contain classes and non-classes, empty or not. For the ones that
4274// are empty classes, we perform the CompressedTuple. If all types in Ts are
4275// empty classes, then CompressedTuple<Ts...> is itself an empty class.
4276//
4277// To access the members, use member .get<N>() function.
4278//
4279// Eg:
4280// phmap::priv::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
4281// t3);
4282// assert(value.get<0>() == 7);
4283// T1& t1 = value.get<1>();
4284// const T2& t2 = value.get<2>();
4285// ...
4286//
4287// https://en.cppreference.com/w/cpp/language/ebo
4288// ---------------------------------------------------------------------------
4289template <typename... Ts>
4290class PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
4291 : private internal_compressed_tuple::CompressedTupleImpl<
4292 CompressedTuple<Ts...>, phmap::index_sequence_for<Ts...>>
4293{
4294private:
4295 template <int I>
4296 using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
4297
4298public:
4299 constexpr CompressedTuple() = default;
4300 explicit constexpr CompressedTuple(Ts... base)
4301 : CompressedTuple::CompressedTupleImpl(phmap::forward<Ts>(base)...) {}
4302
4303 template <int I>
4304 ElemT<I>& get() & {
4306 }
4307
4308 template <int I>
4309 constexpr const ElemT<I>& get() const& {
4311 }
4312
4313 template <int I>
4314 ElemT<I>&& get() && {
4315 return std::move(*this)
4316 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4317 }
4318
4319 template <int I>
4320 constexpr const ElemT<I>&& get() const&& {
4321 return phmap::move(*this)
4322 .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
4323 }
4324};
4325
4326// Explicit specialization for a zero-element tuple
4327// (needed to avoid ambiguous overloads for the default constructor).
4328// ---------------------------------------------------------------------------
4329template <>
4330class PHMAP_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
4331
4332} // namespace priv
4333} // namespace phmap
4334
4335
4336namespace phmap {
4337namespace priv {
4338
4339#ifdef _MSC_VER
4340 #pragma warning(push)
4341 // warning warning C4324: structure was padded due to alignment specifier
4342 #pragma warning(disable : 4324)
4343#endif
4344
4345
4346// ----------------------------------------------------------------------------
4347// Allocates at least n bytes aligned to the specified alignment.
4348// Alignment must be a power of 2. It must be positive.
4349//
4350// Note that many allocators don't honor alignment requirements above certain
4351// threshold (usually either alignof(std::max_align_t) or alignof(void*)).
4352// Allocate() doesn't apply alignment corrections. If the underlying allocator
4353// returns insufficiently alignment pointer, that's what you are going to get.
4354// ----------------------------------------------------------------------------
4355template <size_t Alignment, class Alloc>
4356void* Allocate(Alloc* alloc, size_t n) {
4357 static_assert(Alignment > 0, "");
4358 assert(n && "n must be positive");
4359 struct alignas(Alignment) M {};
4360 using A = typename phmap::allocator_traits<Alloc>::template rebind_alloc<M>;
4361 using AT = typename phmap::allocator_traits<Alloc>::template rebind_traits<M>;
4362 A mem_alloc(*alloc);
4363 void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
4364 assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
4365 "allocator does not respect alignment");
4366 return p;
4367}
4368
4369// ----------------------------------------------------------------------------
4370// The pointer must have been previously obtained by calling
4371// Allocate<Alignment>(alloc, n).
4372// ----------------------------------------------------------------------------
4373template <size_t Alignment, class Alloc>
4374void Deallocate(Alloc* alloc, void* p, size_t n) {
4375 static_assert(Alignment > 0, "");
4376 assert(n && "n must be positive");
4377 struct alignas(Alignment) M {};
4378 using A = typename phmap::allocator_traits<Alloc>::template rebind_alloc<M>;
4379 using AT = typename phmap::allocator_traits<Alloc>::template rebind_traits<M>;
4380 A mem_alloc(*alloc);
4381 AT::deallocate(mem_alloc, static_cast<M*>(p),
4382 (n + sizeof(M) - 1) / sizeof(M));
4383}
4384
4385#ifdef _MSC_VER
4386 #pragma warning(pop)
4387#endif
4388
4389// Helper functions for asan and msan.
4390// ----------------------------------------------------------------------------
4391inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
4392#ifdef ADDRESS_SANITIZER
4393 ASAN_POISON_MEMORY_REGION(m, s);
4394#endif
4395#ifdef MEMORY_SANITIZER
4396 __msan_poison(m, s);
4397#endif
4398 (void)m;
4399 (void)s;
4400}
4401
4402inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
4403#ifdef ADDRESS_SANITIZER
4404 ASAN_UNPOISON_MEMORY_REGION(m, s);
4405#endif
4406#ifdef MEMORY_SANITIZER
4407 __msan_unpoison(m, s);
4408#endif
4409 (void)m;
4410 (void)s;
4411}
4412
4413template <typename T>
4414inline void SanitizerPoisonObject(const T* object) {
4415 SanitizerPoisonMemoryRegion(object, sizeof(T));
4416}
4417
4418template <typename T>
4419inline void SanitizerUnpoisonObject(const T* object) {
4420 SanitizerUnpoisonMemoryRegion(object, sizeof(T));
4421}
4422
4423} // namespace priv
4424} // namespace phmap
4425
4426
4427// ---------------------------------------------------------------------------
4428// thread_annotations.h
4429// ---------------------------------------------------------------------------
4430
4431#if defined(__clang__)
4432 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
4433#else
4434 #define PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
4435#endif
4436
4437#define PHMAP_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
4438#define PHMAP_PT_GUARDED_BY(x) PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
4439
4440#define PHMAP_ACQUIRED_AFTER(...) \
4441 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
4442
4443#define PHMAP_ACQUIRED_BEFORE(...) \
4444 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
4445
4446#define PHMAP_EXCLUSIVE_LOCKS_REQUIRED(...) \
4447 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
4448
4449#define PHMAP_SHARED_LOCKS_REQUIRED(...) \
4450 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
4451
4452#define PHMAP_LOCKS_EXCLUDED(...) \
4453 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
4454
4455#define PHMAP_LOCK_RETURNED(x) \
4456 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
4457
4458#define PHMAP_LOCKABLE \
4459 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
4460
4461#define PHMAP_SCOPED_LOCKABLE \
4462 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
4463
4464#define PHMAP_EXCLUSIVE_LOCK_FUNCTION(...) \
4465 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
4466
4467#define PHMAP_SHARED_LOCK_FUNCTION(...) \
4468 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
4469
4470#define PHMAP_UNLOCK_FUNCTION(...) \
4471 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
4472
4473#define PHMAP_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
4474 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
4475
4476#define PHMAP_SHARED_TRYLOCK_FUNCTION(...) \
4477 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
4478
4479#define PHMAP_ASSERT_EXCLUSIVE_LOCK(...) \
4480 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
4481
4482#define PHMAP_ASSERT_SHARED_LOCK(...) \
4483 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
4484
4485#define PHMAP_NO_THREAD_SAFETY_ANALYSIS \
4486 PHMAP_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
4487
4488//------------------------------------------------------------------------------
4489// Tool-Supplied Annotations
4490//------------------------------------------------------------------------------
4491
4492// TS_UNCHECKED should be placed around lock expressions that are not valid
4493// C++ syntax, but which are present for documentation purposes. These
4494// annotations will be ignored by the analysis.
4495#define PHMAP_TS_UNCHECKED(x) ""
4496
4497// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
4498// It is used by automated tools to mark and disable invalid expressions.
4499// The annotation should either be fixed, or changed to TS_UNCHECKED.
4500#define PHMAP_TS_FIXME(x) ""
4501
4502// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
4503// a particular function. However, this attribute is used to mark functions
4504// that are incorrect and need to be fixed. It is used by automated tools to
4505// avoid breaking the build when the analysis is updated.
4506// Code owners are expected to eventually fix the routine.
4507#define PHMAP_NO_THREAD_SAFETY_ANALYSIS_FIXME PHMAP_NO_THREAD_SAFETY_ANALYSIS
4508
4509// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY
4510// annotation that needs to be fixed, because it is producing thread safety
4511// warning. It disables the GUARDED_BY.
4512#define PHMAP_GUARDED_BY_FIXME(x)
4513
4514// Disables warnings for a single read operation. This can be used to avoid
4515// warnings when it is known that the read is not actually involved in a race,
4516// but the compiler cannot confirm that.
4517#define PHMAP_TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
4518
4519
4520namespace phmap {
4521namespace thread_safety_analysis {
4522
4523// Takes a reference to a guarded data member, and returns an unguarded
4524// reference.
4525template <typename T>
4526inline const T& ts_unchecked_read(const T& v) PHMAP_NO_THREAD_SAFETY_ANALYSIS {
4527 return v;
4528}
4529
4530template <typename T>
4531inline T& ts_unchecked_read(T& v) PHMAP_NO_THREAD_SAFETY_ANALYSIS {
4532 return v;
4533}
4534
4535} // namespace thread_safety_analysis
4536
4537namespace priv {
4538
4539namespace memory_internal {
4540
4541// ----------------------------------------------------------------------------
4542// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and
4543// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and
4544// offsetof(Pair, second) respectively. Otherwise they are -1.
4545//
4546// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout
4547// type, which is non-portable.
4548// ----------------------------------------------------------------------------
4549template <class Pair, class = std::true_type>
4550struct OffsetOf {
4551 static constexpr size_t kFirst = (size_t)-1;
4552 static constexpr size_t kSecond = (size_t)-1;
4553};
4554
4555template <class Pair>
4556struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type>
4557{
4558 static constexpr size_t kFirst = offsetof(Pair, first);
4559 static constexpr size_t kSecond = offsetof(Pair, second);
4560};
4561
4562// ----------------------------------------------------------------------------
4563template <class K, class V>
4565{
4566private:
4567 struct Pair {
4568 K first;
4569 V second;
4570 };
4571
4572 // Is P layout-compatible with Pair?
4573 template <class P>
4574 static constexpr bool LayoutCompatible() {
4575 return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&
4576 alignof(P) == alignof(Pair) &&
4581 }
4582
4583public:
4584 // Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are,
4585 // then it is safe to store them in a union and read from either.
4586 static constexpr bool value = std::is_standard_layout<K>() &&
4587 std::is_standard_layout<Pair>() &&
4589 LayoutCompatible<std::pair<K, V>>() &&
4590 LayoutCompatible<std::pair<const K, V>>();
4591};
4592
4593} // namespace memory_internal
4594
4595// ----------------------------------------------------------------------------
4596// The internal storage type for key-value containers like flat_hash_map.
4597//
4598// It is convenient for the value_type of a flat_hash_map<K, V> to be
4599// pair<const K, V>; the "const K" prevents accidental modification of the key
4600// when dealing with the reference returned from find() and similar methods.
4601// However, this creates other problems; we want to be able to emplace(K, V)
4602// efficiently with move operations, and similarly be able to move a
4603// pair<K, V> in insert().
4604//
4605// The solution is this union, which aliases the const and non-const versions
4606// of the pair. This also allows flat_hash_map<const K, V> to work, even though
4607// that has the same efficiency issues with move in emplace() and insert() -
4608// but people do it anyway.
4609//
4610// If kMutableKeys is false, only the value member can be accessed.
4611//
4612// If kMutableKeys is true, key can be accessed through all slots while value
4613// and mutable_value must be accessed only via INITIALIZED slots. Slots are
4614// created and destroyed via mutable_value so that the key can be moved later.
4615//
4616// Accessing one of the union fields while the other is active is safe as
4617// long as they are layout-compatible, which is guaranteed by the definition of
4618// kMutableKeys. For C++11, the relevant section of the standard is
4619// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
4620// ----------------------------------------------------------------------------
4621template <class K, class V>
4623{
4624 map_slot_type() {}
4625 ~map_slot_type() = delete;
4626 map_slot_type(const map_slot_type&) = delete;
4627 map_slot_type& operator=(const map_slot_type&) = delete;
4628
4629 using value_type = std::pair<const K, V>;
4630 using mutable_value_type = std::pair<K, V>;
4631
4632 value_type value;
4633 mutable_value_type mutable_value;
4634 K key;
4635};
4636
4637// ----------------------------------------------------------------------------
4638// ----------------------------------------------------------------------------
4639template <class K, class V>
4641{
4643 using value_type = std::pair<const K, V>;
4644 using mutable_value_type = std::pair<K, V>;
4645
4646private:
4647 static void emplace(slot_type* slot) {
4648 // The construction of union doesn't do anything at runtime but it allows us
4649 // to access its members without violating aliasing rules.
4650 new (slot) slot_type;
4651 }
4652 // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
4653 // or the other via slot_type. We are also free to access the key via
4654 // slot_type::key in this case.
4656
4657public:
4658 static value_type& element(slot_type* slot) { return slot->value; }
4659 static const value_type& element(const slot_type* slot) {
4660 return slot->value;
4661 }
4662
4663 static const K& key(const slot_type* slot) {
4664 return kMutableKeys::value ? slot->key : slot->value.first;
4665 }
4666
4667 template <class Allocator, class... Args>
4668 static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
4669 emplace(slot);
4670 if (kMutableKeys::value) {
4671 phmap::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value,
4672 std::forward<Args>(args)...);
4673 } else {
4675 std::forward<Args>(args)...);
4676 }
4677 }
4678
4679 // Construct this slot by moving from another slot.
4680 template <class Allocator>
4681 static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {
4682 emplace(slot);
4683 if (kMutableKeys::value) {
4685 *alloc, &slot->mutable_value, std::move(other->mutable_value));
4686 } else {
4688 std::move(other->value));
4689 }
4690 }
4691
4692 template <class Allocator>
4693 static void destroy(Allocator* alloc, slot_type* slot) {
4694 if (kMutableKeys::value) {
4695 phmap::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value);
4696 } else {
4697 phmap::allocator_traits<Allocator>::destroy(*alloc, &slot->value);
4698 }
4699 }
4700
4701 template <class Allocator>
4702 static void transfer(Allocator* alloc, slot_type* new_slot,
4703 slot_type* old_slot) {
4704 emplace(new_slot);
4705 if (kMutableKeys::value) {
4707 *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
4708 } else {
4709 phmap::allocator_traits<Allocator>::construct(*alloc, &new_slot->value,
4710 std::move(old_slot->value));
4711 }
4712 destroy(alloc, old_slot);
4713 }
4714
4715 template <class Allocator>
4716 static void swap(Allocator* alloc, slot_type* a, slot_type* b) {
4717 if (kMutableKeys::value) {
4718 using std::swap;
4719 swap(a->mutable_value, b->mutable_value);
4720 } else {
4721 value_type tmp = std::move(a->value);
4724 std::move(b->value));
4727 std::move(tmp));
4728 }
4729 }
4730
4731 template <class Allocator>
4732 static void move(Allocator* alloc, slot_type* src, slot_type* dest) {
4733 if (kMutableKeys::value) {
4734 dest->mutable_value = std::move(src->mutable_value);
4735 } else {
4736 phmap::allocator_traits<Allocator>::destroy(*alloc, &dest->value);
4738 std::move(src->value));
4739 }
4740 }
4741
4742 template <class Allocator>
4743 static void move(Allocator* alloc, slot_type* first, slot_type* last,
4744 slot_type* result) {
4745 for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
4746 move(alloc, src, dest);
4747 }
4748};
4749
4750} // namespace priv
4751} // phmap
4752
4753
4754namespace phmap {
4755
4756#ifdef BOOST_THREAD_LOCK_OPTIONS_HPP
4757 using defer_lock_t = boost::defer_lock_t;
4758 using try_to_lock_t = boost::try_to_lock_t;
4759 using adopt_lock_t = boost::adopt_lock_t;
4760#else
4761 struct adopt_lock_t { explicit adopt_lock_t() = default; };
4762 struct defer_lock_t { explicit defer_lock_t() = default; };
4763 struct try_to_lock_t { explicit try_to_lock_t() = default; };
4764#endif
4765
4766// -----------------------------------------------------------------------------
4767// NullMutex
4768// -----------------------------------------------------------------------------
4769// A class that implements the Mutex interface, but does nothing. This is to be
4770// used as a default template parameters for classes who provide optional
4771// internal locking (like phmap::parallel_flat_hash_map).
4772// -----------------------------------------------------------------------------
4774public:
4775 NullMutex() {}
4776 ~NullMutex() {}
4777 void lock() {}
4778 void unlock() {}
4779 bool try_lock() { return true; }
4780 void lock_shared() {}
4781 void unlock_shared() {}
4782 bool try_lock_shared() { return true; }
4783};
4784
4785// ------------------------ lockable object used internally -------------------------
4786template <class MutexType>
4788{
4789public:
4790 // ----------------------------------------------------
4792 {
4793 using mutex_type = MutexType;
4794 DoNothing() noexcept {}
4795 explicit DoNothing(mutex_type& ) noexcept {}
4796 explicit DoNothing(mutex_type& , mutex_type&) noexcept {}
4797 DoNothing(mutex_type&, phmap::adopt_lock_t) noexcept {}
4798 DoNothing(mutex_type&, phmap::defer_lock_t) noexcept {}
4799 DoNothing(mutex_type&, phmap::try_to_lock_t) {}
4800 template<class T> explicit DoNothing(T&&) {}
4801 DoNothing& operator=(const DoNothing&) { return *this; }
4802 DoNothing& operator=(DoNothing&&) { return *this; }
4803 void swap(DoNothing &) {}
4804 bool owns_lock() const noexcept { return true; }
4805 };
4806
4807 // ----------------------------------------------------
4809 {
4810 public:
4811 using mutex_type = MutexType;
4812
4813 WriteLock() : m_(nullptr), locked_(false) {}
4814
4815 explicit WriteLock(mutex_type &m) : m_(&m) {
4816 m_->lock();
4817 locked_ = true;
4818 }
4819
4820 WriteLock(mutex_type& m, adopt_lock_t) noexcept :
4821 m_(&m), locked_(true)
4822 {}
4823
4824 WriteLock(mutex_type& m, defer_lock_t) noexcept :
4825 m_(&m), locked_(false)
4826 {}
4827
4828 WriteLock(mutex_type& m, try_to_lock_t) :
4829 m_(&m), locked_(false) {
4830 m_->try_lock();
4831 }
4832
4833 WriteLock(WriteLock &&o) :
4834 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4835 o.locked_ = false;
4836 o.m_ = nullptr;
4837 }
4838
4839 WriteLock& operator=(WriteLock&& other) {
4840 WriteLock temp(std::move(other));
4841 swap(temp);
4842 return *this;
4843 }
4844
4845 ~WriteLock() {
4846 if (locked_)
4847 m_->unlock();
4848 }
4849
4850 void lock() {
4851 if (!locked_) {
4852 m_->lock();
4853 locked_ = true;
4854 }
4855 }
4856
4857 void unlock() {
4858 if (locked_) {
4859 m_->unlock();
4860 locked_ = false;
4861 }
4862 }
4863
4864 bool try_lock() {
4865 if (locked_)
4866 return true;
4867 locked_ = m_->try_lock();
4868 return locked_;
4869 }
4870
4871 bool owns_lock() const noexcept { return locked_; }
4872
4873 void swap(WriteLock &o) noexcept {
4874 std::swap(m_, o.m_);
4875 std::swap(locked_, o.locked_);
4876 }
4877
4878 mutex_type *mutex() const noexcept { return m_; }
4879
4880 private:
4881 mutex_type *m_;
4882 bool locked_;
4883 };
4884
4885 // ----------------------------------------------------
4887 {
4888 public:
4889 using mutex_type = MutexType;
4890
4891 ReadLock() : m_(nullptr), locked_(false) {}
4892
4893 explicit ReadLock(mutex_type &m) : m_(&m) {
4894 m_->lock_shared();
4895 locked_ = true;
4896 }
4897
4898 ReadLock(mutex_type& m, adopt_lock_t) noexcept :
4899 m_(&m), locked_(true)
4900 {}
4901
4902 ReadLock(mutex_type& m, defer_lock_t) noexcept :
4903 m_(&m), locked_(false)
4904 {}
4905
4906 ReadLock(mutex_type& m, try_to_lock_t) :
4907 m_(&m), locked_(false) {
4908 m_->try_lock_shared();
4909 }
4910
4911 ReadLock(ReadLock &&o) :
4912 m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
4913 o.locked_ = false;
4914 o.m_ = nullptr;
4915 }
4916
4917 ReadLock& operator=(ReadLock&& other) {
4918 ReadLock temp(std::move(other));
4919 swap(temp);
4920 return *this;
4921 }
4922
4923 ~ReadLock() {
4924 if (locked_)
4925 m_->unlock_shared();
4926 }
4927
4928 void lock() {
4929 if (!locked_) {
4930 m_->lock_shared();
4931 locked_ = true;
4932 }
4933 }
4934
4935 void unlock() {
4936 if (locked_) {
4937 m_->unlock_shared();
4938 locked_ = false;
4939 }
4940 }
4941
4942 bool try_lock() {
4943 if (locked_)
4944 return true;
4945 locked_ = m_->try_lock_shared();
4946 return locked_;
4947 }
4948
4949 bool owns_lock() const noexcept { return locked_; }
4950
4951 void swap(ReadLock &o) noexcept {
4952 std::swap(m_, o.m_);
4953 std::swap(locked_, o.locked_);
4954 }
4955
4956 mutex_type *mutex() const noexcept { return m_; }
4957
4958 private:
4959 mutex_type *m_;
4960 bool locked_;
4961 };
4962
4963 // ----------------------------------------------------
4965 {
4966 public:
4967 using mutex_type = MutexType;
4968
4969 explicit WriteLocks(mutex_type& m1, mutex_type& m2) :
4970 _m1(m1), _m2(m2)
4971 {
4972 std::lock(m1, m2);
4973 }
4974
4975 WriteLocks(adopt_lock_t, mutex_type& m1, mutex_type& m2) :
4976 _m1(m1), _m2(m2)
4977 { // adopt means we already own the mutexes
4978 }
4979
4980 ~WriteLocks()
4981 {
4982 _m1.unlock();
4983 _m2.unlock();
4984 }
4985
4986 WriteLocks(WriteLocks const&) = delete;
4987 WriteLocks& operator=(WriteLocks const&) = delete;
4988 private:
4989 mutex_type& _m1;
4990 mutex_type& _m2;
4991 };
4992
4993 // ----------------------------------------------------
4995 {
4996 public:
4997 using mutex_type = MutexType;
4998
4999 explicit ReadLocks(mutex_type& m1, mutex_type& m2) :
5000 _m1(m1), _m2(m2)
5001 {
5002 _m1.lock_shared();
5003 _m2.lock_shared();
5004 }
5005
5006 ReadLocks(adopt_lock_t, mutex_type& m1, mutex_type& m2) :
5007 _m1(m1), _m2(m2)
5008 { // adopt means we already own the mutexes
5009 }
5010
5011 ~ReadLocks()
5012 {
5013 _m1.unlock_shared();
5014 _m2.unlock_shared();
5015 }
5016
5017 ReadLocks(ReadLocks const&) = delete;
5018 ReadLocks& operator=(ReadLocks const&) = delete;
5019 private:
5020 mutex_type& _m1;
5021 mutex_type& _m2;
5022 };
5023};
5024
5025// ------------------------ holds a mutex ------------------------------------
5026// Default implementation for Lockable, should work fine for std::mutex
5027// -----------------------------------
5028// use as:
5029// using Lockable = phmap::LockableImpl<mutex_type>;
5030// Lockable m;
5031//
5032// Lockable::UpgradeLock read_lock(m); // take a upgradable lock
5033//
5034// {
5035// Lockable::UpgradeToUnique unique_lock(read_lock);
5036// // now locked for write
5037// }
5038//
5039// ---------------------------------------------------------------------------
5040// Generic mutex support (always write locks)
5041// --------------------------------------------------------------------------
5042template <class Mtx_>
5043class LockableImpl : public Mtx_
5044{
5045public:
5046 using mutex_type = Mtx_;
5048 using SharedLock = typename Base::WriteLock;
5049 using UpgradeLock = typename Base::WriteLock;
5050 using UniqueLock = typename Base::WriteLock;
5051 using SharedLocks = typename Base::WriteLocks;
5052 using UniqueLocks = typename Base::WriteLocks;
5053 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5054};
5055
5056// ---------------------------------------------------------------------------
5057// Null mutex (no-op) - when we don't want internal synchronization
5058// ---------------------------------------------------------------------------
5059template <>
5061{
5062public:
5065 using SharedLock = typename Base::DoNothing;
5066 using UpgradeLock = typename Base::DoNothing;
5067 using UniqueLock = typename Base::DoNothing;
5068 using UpgradeToUnique = typename Base::DoNothing;
5069 using SharedLocks = typename Base::DoNothing;
5070 using UniqueLocks = typename Base::DoNothing;
5071};
5072
5073// --------------------------------------------------------------------------
5074// Abseil Mutex support (read and write lock support)
5075// --------------------------------------------------------------------------
5076#ifdef ABSL_SYNCHRONIZATION_MUTEX_H_
5077
5078 struct AbslMutex : protected absl::Mutex
5079 {
5080 void lock() { this->Lock(); }
5081 void unlock() { this->Unlock(); }
5082 void try_lock() { this->TryLock(); }
5083 void lock_shared() { this->ReaderLock(); }
5084 void unlock_shared() { this->ReaderUnlock(); }
5085 void try_lock_shared() { this->ReaderTryLock(); }
5086 };
5087
5088 template <>
5089 class LockableImpl<absl::Mutex> : public AbslMutex
5090 {
5091 public:
5092 using mutex_type = phmap::AbslMutex;
5093 using Base = LockableBaseImpl<phmap::AbslMutex>;
5094 using SharedLock = typename Base::ReadLock;
5095 using UpgradeLock = typename Base::WriteLock;
5096 using UniqueLock = typename Base::WriteLock;
5097 using SharedLocks = typename Base::ReadLocks;
5098 using UniqueLocks = typename Base::WriteLocks;
5099 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5100 };
5101
5102#endif
5103
5104// --------------------------------------------------------------------------
5105// Boost shared_mutex support (read and write lock support)
5106// --------------------------------------------------------------------------
5107#ifdef BOOST_THREAD_SHARED_MUTEX_HPP
5108
5109#if 1
5110 // ---------------------------------------------------------------------------
5111 template <>
5112 class LockableImpl<boost::shared_mutex> : public boost::shared_mutex
5113 {
5114 public:
5115 using mutex_type = boost::shared_mutex;
5116 using Base = LockableBaseImpl<boost::shared_mutex>;
5117 using SharedLock = boost::shared_lock<mutex_type>;
5118 using UpgradeLock = boost::unique_lock<mutex_type>; // assume can't upgrade
5119 using UniqueLock = boost::unique_lock<mutex_type>;
5120 using SharedLocks = typename Base::ReadLocks;
5121 using UniqueLocks = typename Base::WriteLocks;
5122 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5123 };
5124#else
5125 // ---------------------------------------------------------------------------
5126 template <>
5127 class LockableImpl<boost::upgrade_mutex> : public boost::upgrade_mutex
5128 {
5129 public:
5130 using mutex_type = boost::upgrade_mutex;
5131 using SharedLock = boost::shared_lock<mutex_type>;
5132 using UpgradeLock = boost::upgrade_lock<mutex_type>;
5133 using UniqueLock = boost::unique_lock<mutex_type>;
5134 using SharedLocks = typename Base::ReadLocks;
5135 using UniqueLocks = typename Base::WriteLocks;
5136 using UpgradeToUnique = boost::upgrade_to_unique_lock<mutex_type>;
5137 };
5138#endif
5139
5140#endif // BOOST_THREAD_SHARED_MUTEX_HPP
5141
5142// --------------------------------------------------------------------------
5143// std::shared_mutex support (read and write lock support)
5144// --------------------------------------------------------------------------
5145#ifdef PHMAP_HAVE_SHARED_MUTEX
5146
5147 // ---------------------------------------------------------------------------
5148 template <>
5149 class LockableImpl<std::shared_mutex> : public std::shared_mutex
5150 {
5151 public:
5152 using mutex_type = std::shared_mutex;
5153 using Base = LockableBaseImpl<std::shared_mutex>;
5154 using SharedLock = std::shared_lock<mutex_type>;
5155 using UpgradeLock = std::unique_lock<mutex_type>; // assume can't upgrade
5156 using UniqueLock = std::unique_lock<mutex_type>;
5157 using SharedLocks = typename Base::ReadLocks;
5158 using UniqueLocks = typename Base::WriteLocks;
5159 using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
5160 };
5161#endif // PHMAP_HAVE_SHARED_MUTEX
5162
5163
5164} // phmap
5165
5166#ifdef _MSC_VER
5167 #pragma warning(pop)
5168#endif
5169
5170
5171#endif // phmap_base_h_guard_
A generic couple structure.
Definition GuCookingConvexPolygonsBuilder.cpp:76
Definition phmap_base.h:4887
Definition phmap_base.h:4995
Definition phmap_base.h:4809
Definition phmap_base.h:4965
Definition phmap_base.h:4788
Definition phmap_base.h:5044
Definition phmap_base.h:4773
Definition phmap_base.h:3110
Definition phmap_base.h:1821
Definition phmap_base.h:4293
@ Aligned
Definition Constants.h:240
Definition phmap_base.h:76
Definition phmap_base.h:85
Definition phmap_base.h:4792
Definition phmap_base.h:4761
Definition phmap_base.h:1599
Definition phmap_base.h:1379
Definition phmap_base.h:840
Definition phmap_base.h:823
Definition phmap_base.h:806
Definition phmap_base.h:853
Definition phmap_base.h:779
Definition phmap_base.h:753
Definition phmap_base.h:743
Definition phmap_base.h:200
Definition phmap_base.h:1606
Definition phmap_base.h:4762
Definition phmap_base.h:224
Definition phmap_base.h:1019
Definition phmap_base.h:990
Definition phmap_base.h:1006
Definition phmap_base.h:906
Definition phmap_base.h:596
Definition phmap_base.h:163
Definition phmap_base.h:168
Definition phmap_base.h:260
Definition phmap_base.h:254
Definition phmap_base.h:242
Definition phmap_base.h:1272
Definition phmap_base.h:1218
Definition phmap_base.h:1264
Definition phmap_base.h:1159
Definition phmap_base.h:1311
Definition phmap_base.h:1282
Definition phmap_base.h:1291
Definition phmap_base.h:237
Definition phmap_base.h:1697
Definition phmap_base.h:1711
Definition phmap_base.h:1325
Definition phmap_base.h:4641
Definition phmap_base.h:4550
Definition phmap_base.h:2787
Definition phmap_base.h:2981
Definition phmap_base.h:3014
Definition phmap_base.h:3022
Definition phmap_base.h:4763
Definition phmap_base.h:357
Definition phmap_base.h:95
Definition phmap_base.h:134
Definition phmap_base.h:922
Definition phmap_base.h:938
Definition phmap_base.h:4623