Coverage Report

Created: 2023-06-07 07:15

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