Coverage Report

Created: 2025-12-31 07:01

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