Coverage Report

Created: 2025-07-11 07:01

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