Use more C++17
[WebKit-https.git] / Source / WTF / wtf / StdLibExtras.h
1 /*
2  * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2013 Patrick Gansterer <paroga@paroga.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #ifndef WTF_StdLibExtras_h
28 #define WTF_StdLibExtras_h
29
30 #include <algorithm>
31 #include <cstring>
32 #include <memory>
33 #include <type_traits>
34 #include <wtf/Assertions.h>
35 #include <wtf/CheckedArithmetic.h>
36 #include <wtf/Compiler.h>
37
38 // Use this macro to declare and define a debug-only global variable that may have a
39 // non-trivial constructor and destructor. When building with clang, this will suppress
40 // warnings about global constructors and exit-time destructors.
41 #define DEFINE_GLOBAL_FOR_LOGGING(type, name, arguments) \
42     _Pragma("clang diagnostic push") \
43     _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
44     _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
45     static type name arguments; \
46     _Pragma("clang diagnostic pop")
47
48 #ifndef NDEBUG
49 #if COMPILER(CLANG)
50 #define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) DEFINE_GLOBAL_FOR_LOGGING(type, name, arguments)
51 #else
52 #define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \
53     static type name arguments;
54 #endif // COMPILER(CLANG)
55 #else
56 #define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments)
57 #endif // NDEBUG
58
59 // OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes.
60 // The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
61 // NULL can cause compiler problems, especially in cases of multiple inheritance.
62 #define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
63
64 #define CAST_OFFSET(from, to) (reinterpret_cast<uintptr_t>(static_cast<to>((reinterpret_cast<from>(0x4000)))) - 0x4000)
65
66 // STRINGIZE: Can convert any value to quoted string, even expandable macros
67 #define STRINGIZE(exp) #exp
68 #define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
69
70 // WTF_CONCAT: concatenate two symbols into one, even expandable macros
71 #define WTF_CONCAT_INTERNAL_DONT_USE(a, b) a ## b
72 #define WTF_CONCAT(a, b) WTF_CONCAT_INTERNAL_DONT_USE(a, b)
73
74
75 /*
76  * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where
77  * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC:
78  * increases required alignment of target type.
79  *
80  * An implicit or an extra static_cast<void*> bypasses the warning.
81  * For more info see the following bugzilla entries:
82  * - https://bugs.webkit.org/show_bug.cgi?id=38045
83  * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976
84  */
85 #if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC_OR_CLANG)
86 template<typename Type>
87 inline bool isPointerTypeAlignmentOkay(Type* ptr)
88 {
89     return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
90 }
91
92 template<typename TypePtr>
93 inline TypePtr reinterpret_cast_ptr(void* ptr)
94 {
95     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
96     return reinterpret_cast<TypePtr>(ptr);
97 }
98
99 template<typename TypePtr>
100 inline TypePtr reinterpret_cast_ptr(const void* ptr)
101 {
102     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
103     return reinterpret_cast<TypePtr>(ptr);
104 }
105 #else
106 template<typename Type>
107 inline bool isPointerTypeAlignmentOkay(Type*)
108 {
109     return true;
110 }
111 #define reinterpret_cast_ptr reinterpret_cast
112 #endif
113
114 namespace WTF {
115
116 enum CheckMoveParameterTag { CheckMoveParameter };
117
118 static const size_t KB = 1024;
119 static const size_t MB = 1024 * 1024;
120 static const size_t GB = 1024 * 1024 * 1024;
121
122 inline bool isPointerAligned(void* p)
123 {
124     return !((intptr_t)(p) & (sizeof(char*) - 1));
125 }
126
127 inline bool is8ByteAligned(void* p)
128 {
129     return !((uintptr_t)(p) & (sizeof(double) - 1));
130 }
131
132 /*
133  * C++'s idea of a reinterpret_cast lacks sufficient cojones.
134  */
135 template<typename ToType, typename FromType>
136 inline ToType bitwise_cast(FromType from)
137 {
138     static_assert(sizeof(FromType) == sizeof(ToType), "bitwise_cast size of FromType and ToType must be equal!");
139 #if COMPILER_SUPPORTS(BUILTIN_IS_TRIVIALLY_COPYABLE)
140     // Not all recent STL implementations support the std::is_trivially_copyable type trait. Work around this by only checking on toolchains which have the equivalent compiler intrinsic.
141     static_assert(__is_trivially_copyable(ToType), "bitwise_cast of non-trivially-copyable type!");
142     static_assert(__is_trivially_copyable(FromType), "bitwise_cast of non-trivially-copyable type!");
143 #endif
144     typename std::remove_const<ToType>::type to { };
145     std::memcpy(static_cast<void*>(&to), static_cast<void*>(&from), sizeof(to));
146     return to;
147 }
148
149 template<typename ToType, typename FromType>
150 inline ToType safeCast(FromType value)
151 {
152     RELEASE_ASSERT(isInBounds<ToType>(value));
153     return static_cast<ToType>(value);
154 }
155
156 // Returns a count of the number of bits set in 'bits'.
157 inline size_t bitCount(unsigned bits)
158 {
159     bits = bits - ((bits >> 1) & 0x55555555);
160     bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
161     return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
162 }
163
164 inline size_t bitCount(uint64_t bits)
165 {
166     return bitCount(static_cast<unsigned>(bits)) + bitCount(static_cast<unsigned>(bits >> 32));
167 }
168
169 // Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array.
170 template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size];
171 // GCC needs some help to deduce a 0 length array.
172 #if COMPILER(GCC_OR_CLANG)
173 template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0];
174 #endif
175 #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array))
176
177 ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl0(size_t remainderMask, size_t x)
178 {
179     return (x + remainderMask) & ~remainderMask;
180 }
181
182 ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl(size_t divisor, size_t x)
183 {
184     return roundUpToMultipleOfImpl0(divisor - 1, x);
185 }
186
187 // Efficient implementation that takes advantage of powers of two.
188 inline size_t roundUpToMultipleOf(size_t divisor, size_t x)
189 {
190     ASSERT(divisor && !(divisor & (divisor - 1)));
191     return roundUpToMultipleOfImpl(divisor, x);
192 }
193
194 template<size_t divisor> inline constexpr size_t roundUpToMultipleOf(size_t x)
195 {
196     static_assert(divisor && !(divisor & (divisor - 1)), "divisor must be a power of two!");
197     return roundUpToMultipleOfImpl(divisor, x);
198 }
199
200 template<size_t divisor, typename T> inline T* roundUpToMultipleOf(T* x)
201 {
202     static_assert(sizeof(T*) == sizeof(size_t), "");
203     return reinterpret_cast<T*>(roundUpToMultipleOf<divisor>(reinterpret_cast<size_t>(x)));
204 }
205
206 enum BinarySearchMode {
207     KeyMustBePresentInArray,
208     KeyMightNotBePresentInArray,
209     ReturnAdjacentElementIfKeyIsNotPresent
210 };
211
212 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey, BinarySearchMode mode>
213 inline ArrayElementType* binarySearchImpl(ArrayType& array, size_t size, KeyType key, const ExtractKey& extractKey = ExtractKey())
214 {
215     size_t offset = 0;
216     while (size > 1) {
217         size_t pos = (size - 1) >> 1;
218         KeyType val = extractKey(&array[offset + pos]);
219         
220         if (val == key)
221             return &array[offset + pos];
222         // The item we are looking for is smaller than the item being check; reduce the value of 'size',
223         // chopping off the right hand half of the array.
224         if (key < val)
225             size = pos;
226         // Discard all values in the left hand half of the array, up to and including the item at pos.
227         else {
228             size -= (pos + 1);
229             offset += (pos + 1);
230         }
231
232         ASSERT(mode != KeyMustBePresentInArray || size);
233     }
234     
235     if (mode == KeyMightNotBePresentInArray && !size)
236         return 0;
237     
238     ArrayElementType* result = &array[offset];
239
240     if (mode == KeyMightNotBePresentInArray && key != extractKey(result))
241         return 0;
242
243     if (mode == KeyMustBePresentInArray) {
244         ASSERT(size == 1);
245         ASSERT(key == extractKey(result));
246     }
247
248     return result;
249 }
250
251 // If the element is not found, crash if asserts are enabled, and behave like approximateBinarySearch in release builds.
252 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
253 inline ArrayElementType* binarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
254 {
255     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMustBePresentInArray>(array, size, key, extractKey);
256 }
257
258 // Return zero if the element is not found.
259 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
260 inline ArrayElementType* tryBinarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
261 {
262     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMightNotBePresentInArray>(array, size, key, extractKey);
263 }
264
265 // Return the element that is either to the left, or the right, of where the element would have been found.
266 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
267 inline ArrayElementType* approximateBinarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
268 {
269     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, ReturnAdjacentElementIfKeyIsNotPresent>(array, size, key, extractKey);
270 }
271
272 // Variants of the above that use const.
273 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
274 inline ArrayElementType* binarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
275 {
276     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMustBePresentInArray>(const_cast<ArrayType&>(array), size, key, extractKey);
277 }
278 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
279 inline ArrayElementType* tryBinarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
280 {
281     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMightNotBePresentInArray>(const_cast<ArrayType&>(array), size, key, extractKey);
282 }
283 template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey>
284 inline ArrayElementType* approximateBinarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey())
285 {
286     return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, ReturnAdjacentElementIfKeyIsNotPresent>(const_cast<ArrayType&>(array), size, key, extractKey);
287 }
288
289 template<typename VectorType, typename ElementType>
290 inline void insertIntoBoundedVector(VectorType& vector, size_t size, const ElementType& element, size_t index)
291 {
292     for (size_t i = size; i-- > index + 1;)
293         vector[i] = vector[i - 1];
294     vector[index] = element;
295 }
296
297 // This is here instead of CompilationThread.h to prevent that header from being included
298 // everywhere. The fact that this method, and that header, exist outside of JSC is a bug.
299 // https://bugs.webkit.org/show_bug.cgi?id=131815
300 WTF_EXPORT_PRIVATE bool isCompilationThread();
301
302 template<typename Func>
303 bool isStatelessLambda()
304 {
305     return std::is_empty<Func>::value;
306 }
307
308 template<typename ResultType, typename Func, typename... ArgumentTypes>
309 ResultType callStatelessLambda(ArgumentTypes&&... arguments)
310 {
311     uint64_t data[(sizeof(Func) + sizeof(uint64_t) - 1) / sizeof(uint64_t)];
312     memset(data, 0, sizeof(data));
313     return (*bitwise_cast<Func*>(data))(std::forward<ArgumentTypes>(arguments)...);
314 }
315
316 template<typename T, typename U>
317 bool checkAndSet(T& left, U right)
318 {
319     if (left == right)
320         return false;
321     left = right;
322     return true;
323 }
324
325 template<typename T>
326 bool findBitInWord(T word, size_t& index, size_t endIndex, bool value)
327 {
328     static_assert(std::is_unsigned<T>::value, "Type used in findBitInWord must be unsigned");
329     
330     word >>= index;
331     
332     while (index < endIndex) {
333         if ((word & 1) == static_cast<T>(value))
334             return true;
335         index++;
336         word >>= 1;
337     }
338     
339     index = endIndex;
340     return false;
341 }
342
343 // Visitor adapted from http://stackoverflow.com/questions/25338795/is-there-a-name-for-this-tuple-creation-idiom
344
345 template <class A, class... B>
346 struct Visitor : Visitor<A>, Visitor<B...> {
347     Visitor(A a, B... b)
348         : Visitor<A>(a)
349         , Visitor<B...>(b...)
350     {
351     }
352
353     using Visitor<A>::operator ();
354     using Visitor<B...>::operator ();
355 };
356   
357 template <class A>
358 struct Visitor<A> : A {
359     Visitor(A a)
360         : A(a)
361     {
362     }
363
364     using A::operator();
365 };
366  
367 template <class... F>
368 Visitor<F...> makeVisitor(F... f)
369 {
370     return Visitor<F...>(f...);
371 }
372
373 namespace Detail
374 {
375     template <typename, template <typename...> class>
376     struct IsTemplate_ : std::false_type
377     {
378     };
379
380     template <typename... Ts, template <typename...> class C>
381     struct IsTemplate_<C<Ts...>, C> : std::true_type
382     {
383     };
384 }
385
386 template <typename T, template <typename...> class Template>
387 struct IsTemplate : public std::integral_constant<bool, Detail::IsTemplate_<T, Template>::value> {};
388
389 namespace Detail
390 {
391     template <template <typename...> class Base, typename Derived>
392     struct IsBaseOfTemplateImpl
393     {
394         template <typename... Args>
395         static std::true_type test(Base<Args...>*);
396         static std::false_type test(void*);
397
398         static constexpr const bool value = decltype(test(std::declval<typename std::remove_cv<Derived>::type*>()))::value;
399     };
400 }
401
402 template <template <typename...> class Base, typename Derived>
403 struct IsBaseOfTemplate : public std::integral_constant<bool, Detail::IsBaseOfTemplateImpl<Base, Derived>::value> {};
404
405 template <class T>
406 struct RemoveCVAndReference  {
407     typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
408 };
409
410 template<typename IteratorTypeLeft, typename IteratorTypeRight, typename IteratorTypeDst>
411 IteratorTypeDst mergeDeduplicatedSorted(IteratorTypeLeft leftBegin, IteratorTypeLeft leftEnd, IteratorTypeRight rightBegin, IteratorTypeRight rightEnd, IteratorTypeDst dstBegin)
412 {
413     IteratorTypeLeft leftIter = leftBegin;
414     IteratorTypeRight rightIter = rightBegin;
415     IteratorTypeDst dstIter = dstBegin;
416     
417     if (leftIter < leftEnd && rightIter < rightEnd) {
418         for (;;) {
419             auto left = *leftIter;
420             auto right = *rightIter;
421             if (left < right) {
422                 *dstIter++ = left;
423                 leftIter++;
424                 if (leftIter >= leftEnd)
425                     break;
426             } else if (left == right) {
427                 *dstIter++ = left;
428                 leftIter++;
429                 rightIter++;
430                 if (leftIter >= leftEnd || rightIter >= rightEnd)
431                     break;
432             } else {
433                 *dstIter++ = right;
434                 rightIter++;
435                 if (rightIter >= rightEnd)
436                     break;
437             }
438         }
439     }
440     
441     while (leftIter < leftEnd)
442         *dstIter++ = *leftIter++;
443     while (rightIter < rightEnd)
444         *dstIter++ = *rightIter++;
445     
446     return dstIter;
447 }
448
449 // libstdc++5 does not have constexpr std::tie. Since we cannot redefine std::tie with constexpr, we define WTF::tie instead.
450 // This workaround can be removed after 2019-04 and all users of WTF::tie can be converted to std::tie
451 // For more info see: https://bugs.webkit.org/show_bug.cgi?id=180692 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65978
452 template <class ...Args>
453 inline constexpr std::tuple<Args&...> tie(Args&... values)
454 {
455     return std::tuple<Args&...>(values...);
456 }
457
458 // libstdc++4 does not have constexpr std::min or std::max.
459 // As a workaround this defines WTF::min and WTF::max with constexpr, to be used when a constexpr result is expected.
460 // This workaround can be removed after 2018-06 and all users of WTF::min and WTF::max can be converted to std::min and std::max.
461 // For more info see: https://bugs.webkit.org/show_bug.cgi?id=181160
462 template <class T>
463 inline constexpr const T& min(const T& a, const T& b)
464 {
465     return std::min(a, b);
466 }
467
468 template <class T>
469 inline constexpr const T& max(const T& a, const T& b)
470 {
471     return std::max(a, b);
472 }
473
474 } // namespace WTF
475
476 // This version of placement new omits a 0 check.
477 enum NotNullTag { NotNull };
478 inline void* operator new(size_t, NotNullTag, void* location)
479 {
480     ASSERT(location);
481     return location;
482 }
483
484 // This adds various C++14 features for versions of the STL that may not yet have them.
485 namespace std {
486 #if COMPILER(CLANG) && __cplusplus < 201400L
487 template<class T> struct _Unique_if {
488     typedef unique_ptr<T> _Single_object;
489 };
490
491 template<class T> struct _Unique_if<T[]> {
492     typedef unique_ptr<T[]> _Unknown_bound;
493 };
494
495 template<class T, size_t N> struct _Unique_if<T[N]> {
496     typedef void _Known_bound;
497 };
498
499 template<class T, class... Args> inline typename _Unique_if<T>::_Single_object
500 make_unique(Args&&... args)
501 {
502     return unique_ptr<T>(new T(std::forward<Args>(args)...));
503 }
504
505 template<class T> inline typename _Unique_if<T>::_Unknown_bound
506 make_unique(size_t n)
507 {
508     typedef typename remove_extent<T>::type U;
509     return unique_ptr<T>(new U[n]());
510 }
511
512 template<class T, class... Args> typename _Unique_if<T>::_Known_bound
513 make_unique(Args&&...) = delete;
514
515 // std::exchange
516 template<class T, class U = T>
517 T exchange(T& t, U&& newValue)
518 {
519     T oldValue = std::move(t);
520     t = std::forward<U>(newValue);
521
522     return oldValue;
523 }
524 #endif
525
526 template<WTF::CheckMoveParameterTag, typename T>
527 ALWAYS_INLINE constexpr typename remove_reference<T>::type&& move(T&& value)
528 {
529     static_assert(is_lvalue_reference<T>::value, "T is not an lvalue reference; move() is unnecessary.");
530
531     using NonRefQualifiedType = typename remove_reference<T>::type;
532     static_assert(!is_const<NonRefQualifiedType>::value, "T is const qualified.");
533
534     return move(forward<T>(value));
535 }
536
537 #if __cplusplus < 201703L && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER < 190023918) && !defined(__cpp_lib_logical_traits)
538 template<class...> struct wtf_conjunction_impl;
539 template<> struct wtf_conjunction_impl<> : true_type { };
540 template<class B0> struct wtf_conjunction_impl<B0> : B0 { };
541 template<class B0, class B1> struct wtf_conjunction_impl<B0, B1> : conditional<B0::value, B1, B0>::type { };
542 template<class B0, class B1, class B2, class... Bn> struct wtf_conjunction_impl<B0, B1, B2, Bn...> : conditional<B0::value, wtf_conjunction_impl<B1, B2, Bn...>, B0>::type { };
543 template<class... _Args> struct conjunction : wtf_conjunction_impl<_Args...> { };
544 #endif
545
546 // Provide in_place_t when not building with -std=c++17 or when building with libstdc++ 6, or when building with < Xcode 9.0.
547 // (which doesn't define the _GLIBCXX_RELEASE macro that's been introduced in libstdc++ 7).
548 #if (__cplusplus < 201703L || (defined(__GLIBCXX__) && !defined(_GLIBCXX_RELEASE))) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER < 190023918) && !(PLATFORM(COCOA) && __clang_major__ >= 9)
549
550 // These are inline variable for C++17 and later.
551 #define __IN_PLACE_INLINE_VARIABLE static const
552
553 struct in_place_t {
554     explicit in_place_t() = default;
555 };
556 __IN_PLACE_INLINE_VARIABLE constexpr in_place_t in_place { };
557
558 template <class T> struct in_place_type_t {
559     explicit in_place_type_t() = default;
560 };
561 template <class T>
562 __IN_PLACE_INLINE_VARIABLE constexpr in_place_type_t<T> in_place_type { };
563
564 template <size_t I> struct in_place_index_t {
565     explicit in_place_index_t() = default;
566 };
567 template <size_t I>
568 __IN_PLACE_INLINE_VARIABLE constexpr in_place_index_t<I> in_place_index { };
569 #endif // __cplusplus < 201703L
570
571 enum class ZeroStatus {
572     MayBeZero,
573     NonZero
574 };
575
576 constexpr size_t clz(uint32_t value, ZeroStatus mightBeZero = ZeroStatus::MayBeZero)
577 {
578     if (mightBeZero == ZeroStatus::MayBeZero && value) {
579 #if COMPILER(MSVC)
580         return __lzcnt(value);
581 #else
582         return __builtin_clz(value);
583 #endif
584     }
585     return 32;
586 }
587
588 } // namespace std
589
590 #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
591
592 using WTF::KB;
593 using WTF::MB;
594 using WTF::GB;
595 using WTF::approximateBinarySearch;
596 using WTF::binarySearch;
597 using WTF::bitwise_cast;
598 using WTF::callStatelessLambda;
599 using WTF::checkAndSet;
600 using WTF::findBitInWord;
601 using WTF::insertIntoBoundedVector;
602 using WTF::isCompilationThread;
603 using WTF::isPointerAligned;
604 using WTF::isStatelessLambda;
605 using WTF::is8ByteAligned;
606 using WTF::mergeDeduplicatedSorted;
607 using WTF::roundUpToMultipleOf;
608 using WTF::safeCast;
609 using WTF::tryBinarySearch;
610
611 #endif // WTF_StdLibExtras_h