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