libstdc++
type_traits
Go to the documentation of this file.
1// C++11 <type_traits> -*- C++ -*-
2
3// Copyright (C) 2007-2025 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/type_traits
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_TYPE_TRAITS
30#define _GLIBCXX_TYPE_TRAITS 1
31
32#ifdef _GLIBCXX_SYSHDR
33#pragma GCC system_header
34#endif
35
36#if __cplusplus < 201103L
37# include <bits/c++0x_warning.h>
38#else
39
40#include <bits/c++config.h>
41
42#define __glibcxx_want_bool_constant
43#define __glibcxx_want_bounded_array_traits
44#define __glibcxx_want_has_unique_object_representations
45#define __glibcxx_want_integral_constant_callable
46#define __glibcxx_want_is_aggregate
47#define __glibcxx_want_is_constant_evaluated
48#define __glibcxx_want_is_final
49#define __glibcxx_want_is_invocable
50#define __glibcxx_want_is_layout_compatible
51#define __glibcxx_want_is_nothrow_convertible
52#define __glibcxx_want_is_null_pointer
53#define __glibcxx_want_is_pointer_interconvertible
54#define __glibcxx_want_is_scoped_enum
55#define __glibcxx_want_is_swappable
56#define __glibcxx_want_is_virtual_base_of
57#define __glibcxx_want_logical_traits
58#define __glibcxx_want_reference_from_temporary
59#define __glibcxx_want_remove_cvref
60#define __glibcxx_want_result_of_sfinae
61#define __glibcxx_want_transformation_trait_aliases
62#define __glibcxx_want_type_identity
63#define __glibcxx_want_type_trait_variable_templates
64#define __glibcxx_want_unwrap_ref
65#define __glibcxx_want_void_t
66#include <bits/version.h>
67
68extern "C++"
69{
70namespace std _GLIBCXX_VISIBILITY(default)
71{
72_GLIBCXX_BEGIN_NAMESPACE_VERSION
73
74 template<typename _Tp>
75 class reference_wrapper;
76
77 /**
78 * @defgroup metaprogramming Metaprogramming
79 * @ingroup utilities
80 *
81 * Template utilities for compile-time introspection and modification,
82 * including type classification traits, type property inspection traits
83 * and type transformation traits.
84 *
85 * @since C++11
86 *
87 * @{
88 */
89
90 /// integral_constant
91 template<typename _Tp, _Tp __v>
92 struct integral_constant
93 {
94 static constexpr _Tp value = __v;
95 using value_type = _Tp;
96 using type = integral_constant<_Tp, __v>;
97 constexpr operator value_type() const noexcept { return value; }
98
99#ifdef __cpp_lib_integral_constant_callable // C++ >= 14
100 constexpr value_type operator()() const noexcept { return value; }
101#endif
102 };
103
104#if ! __cpp_inline_variables
105 template<typename _Tp, _Tp __v>
106 constexpr _Tp integral_constant<_Tp, __v>::value;
107#endif
108
109 /// @cond undocumented
110 /// bool_constant for C++11
111 template<bool __v>
112 using __bool_constant = integral_constant<bool, __v>;
113 /// @endcond
114
115 /// The type used as a compile-time boolean with true value.
116 using true_type = __bool_constant<true>;
117
118 /// The type used as a compile-time boolean with false value.
119 using false_type = __bool_constant<false>;
120
121#ifdef __cpp_lib_bool_constant // C++ >= 17
122 /// Alias template for compile-time boolean constant types.
123 /// @since C++17
124 template<bool __v>
125 using bool_constant = __bool_constant<__v>;
126#endif
127
128 // Metaprogramming helper types.
129
130 // Primary template.
131 /// Define a member typedef `type` only if a boolean constant is true.
132 template<bool, typename _Tp = void>
133 struct enable_if
134 { };
135
136 // Partial specialization for true.
137 template<typename _Tp>
138 struct enable_if<true, _Tp>
139 { using type = _Tp; };
140
141 // __enable_if_t (std::enable_if_t for C++11)
142 template<bool _Cond, typename _Tp = void>
143 using __enable_if_t = typename enable_if<_Cond, _Tp>::type;
144
145 template<bool>
146 struct __conditional
147 {
148 template<typename _Tp, typename>
149 using type = _Tp;
150 };
151
152 template<>
153 struct __conditional<false>
154 {
155 template<typename, typename _Up>
156 using type = _Up;
157 };
158
159 // More efficient version of std::conditional_t for internal use (and C++11)
160 template<bool _Cond, typename _If, typename _Else>
161 using __conditional_t
162 = typename __conditional<_Cond>::template type<_If, _Else>;
163
164 /// @cond undocumented
165 template <typename _Type>
166 struct __type_identity
167 { using type = _Type; };
168
169 template<typename _Tp>
170 using __type_identity_t = typename __type_identity<_Tp>::type;
171
172 namespace __detail
173 {
174 // A variadic alias template that resolves to its first argument.
175 template<typename _Tp, typename...>
176 using __first_t = _Tp;
177
178 // These are deliberately not defined.
179 template<typename... _Bn>
180 auto __or_fn(int) -> __first_t<false_type,
181 __enable_if_t<!bool(_Bn::value)>...>;
182
183 template<typename... _Bn>
184 auto __or_fn(...) -> true_type;
185
186 template<typename... _Bn>
187 auto __and_fn(int) -> __first_t<true_type,
188 __enable_if_t<bool(_Bn::value)>...>;
189
190 template<typename... _Bn>
191 auto __and_fn(...) -> false_type;
192 } // namespace detail
193
194 // Like C++17 std::dis/conjunction, but usable in C++11 and resolves
195 // to either true_type or false_type which allows for a more efficient
196 // implementation that avoids recursive class template instantiation.
197 template<typename... _Bn>
198 struct __or_
199 : decltype(__detail::__or_fn<_Bn...>(0))
200 { };
201
202 template<typename... _Bn>
203 struct __and_
204 : decltype(__detail::__and_fn<_Bn...>(0))
205 { };
206
207 template<typename _Pp>
208 struct __not_
209 : __bool_constant<!bool(_Pp::value)>
210 { };
211 /// @endcond
212
213#ifdef __cpp_lib_logical_traits // C++ >= 17
214
215 /// @cond undocumented
216 template<typename... _Bn>
217 inline constexpr bool __or_v = __or_<_Bn...>::value;
218 template<typename... _Bn>
219 inline constexpr bool __and_v = __and_<_Bn...>::value;
220
221 namespace __detail
222 {
223 template<typename /* = void */, typename _B1, typename... _Bn>
224 struct __disjunction_impl
225 { using type = _B1; };
226
227 template<typename _B1, typename _B2, typename... _Bn>
228 struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...>
229 { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; };
230
231 template<typename /* = void */, typename _B1, typename... _Bn>
232 struct __conjunction_impl
233 { using type = _B1; };
234
235 template<typename _B1, typename _B2, typename... _Bn>
236 struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...>
237 { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; };
238 } // namespace __detail
239 /// @endcond
240
241 template<typename... _Bn>
242 struct conjunction
243 : __detail::__conjunction_impl<void, _Bn...>::type
244 { };
245
246 template<>
247 struct conjunction<>
248 : true_type
249 { };
250
251 template<typename... _Bn>
252 struct disjunction
253 : __detail::__disjunction_impl<void, _Bn...>::type
254 { };
255
256 template<>
257 struct disjunction<>
258 : false_type
259 { };
260
261 template<typename _Pp>
262 struct negation
263 : __not_<_Pp>::type
264 { };
265
266 /** @ingroup variable_templates
267 * @{
268 */
269 template<typename... _Bn>
270 inline constexpr bool conjunction_v = conjunction<_Bn...>::value;
271
272 template<typename... _Bn>
273 inline constexpr bool disjunction_v = disjunction<_Bn...>::value;
274
275 template<typename _Pp>
276 inline constexpr bool negation_v = negation<_Pp>::value;
277 /// @}
278
279#endif // __cpp_lib_logical_traits
280
281 // Forward declarations
282 template<typename>
283 struct is_reference;
284 template<typename>
285 struct is_function;
286 template<typename>
287 struct is_void;
288 template<typename>
289 struct remove_cv;
290 template<typename>
291 struct is_const;
292
293 /// @cond undocumented
294 template<typename>
295 struct __is_array_unknown_bounds;
296
297 // Helper functions that return false_type for incomplete classes,
298 // incomplete unions and arrays of known bound from those.
299
300 template <typename _Tp, size_t = sizeof(_Tp)>
301 constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>)
302 { return {}; }
303
304 template <typename _TypeIdentity,
305 typename _NestedType = typename _TypeIdentity::type>
306 constexpr typename __or_<
307 is_reference<_NestedType>,
308 is_function<_NestedType>,
309 is_void<_NestedType>,
310 __is_array_unknown_bounds<_NestedType>
311 >::type __is_complete_or_unbounded(_TypeIdentity)
312 { return {}; }
313
314 // __remove_cv_t (std::remove_cv_t for C++11).
315 template<typename _Tp>
316 using __remove_cv_t = typename remove_cv<_Tp>::type;
317 /// @endcond
318
319 // Primary type categories.
320
321 /// is_void
322 template<typename _Tp>
323 struct is_void
324 : public false_type { };
325
326 template<>
327 struct is_void<void>
328 : public true_type { };
329
330 template<>
331 struct is_void<const void>
332 : public true_type { };
333
334 template<>
335 struct is_void<volatile void>
336 : public true_type { };
337
338 template<>
339 struct is_void<const volatile void>
340 : public true_type { };
341
342 /// @cond undocumented
343 template<typename>
344 struct __is_integral_helper
345 : public false_type { };
346
347 template<>
348 struct __is_integral_helper<bool>
349 : public true_type { };
350
351 template<>
352 struct __is_integral_helper<char>
353 : public true_type { };
354
355 template<>
356 struct __is_integral_helper<signed char>
357 : public true_type { };
358
359 template<>
360 struct __is_integral_helper<unsigned char>
361 : public true_type { };
362
363 // We want is_integral<wchar_t> to be true (and make_signed/unsigned to work)
364 // even when libc doesn't provide working <wchar.h> and related functions,
365 // so don't check _GLIBCXX_USE_WCHAR_T here.
366 template<>
367 struct __is_integral_helper<wchar_t>
368 : public true_type { };
369
370#ifdef _GLIBCXX_USE_CHAR8_T
371 template<>
372 struct __is_integral_helper<char8_t>
373 : public true_type { };
374#endif
375
376 template<>
377 struct __is_integral_helper<char16_t>
378 : public true_type { };
379
380 template<>
381 struct __is_integral_helper<char32_t>
382 : public true_type { };
383
384 template<>
385 struct __is_integral_helper<short>
386 : public true_type { };
387
388 template<>
389 struct __is_integral_helper<unsigned short>
390 : public true_type { };
391
392 template<>
393 struct __is_integral_helper<int>
394 : public true_type { };
395
396 template<>
397 struct __is_integral_helper<unsigned int>
398 : public true_type { };
399
400 template<>
401 struct __is_integral_helper<long>
402 : public true_type { };
403
404 template<>
405 struct __is_integral_helper<unsigned long>
406 : public true_type { };
407
408 template<>
409 struct __is_integral_helper<long long>
410 : public true_type { };
411
412 template<>
413 struct __is_integral_helper<unsigned long long>
414 : public true_type { };
415
416 // Conditionalizing on __STRICT_ANSI__ here will break any port that
417 // uses one of these types for size_t.
418#if defined(__GLIBCXX_TYPE_INT_N_0)
419 __extension__
420 template<>
421 struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
422 : public true_type { };
423
424 __extension__
425 template<>
426 struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
427 : public true_type { };
428#endif
429#if defined(__GLIBCXX_TYPE_INT_N_1)
430 __extension__
431 template<>
432 struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
433 : public true_type { };
434
435 __extension__
436 template<>
437 struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
438 : public true_type { };
439#endif
440#if defined(__GLIBCXX_TYPE_INT_N_2)
441 __extension__
442 template<>
443 struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
444 : public true_type { };
445
446 __extension__
447 template<>
448 struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
449 : public true_type { };
450#endif
451#if defined(__GLIBCXX_TYPE_INT_N_3)
452 __extension__
453 template<>
454 struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
455 : public true_type { };
456
457 __extension__
458 template<>
459 struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
460 : public true_type { };
461#endif
462 /// @endcond
463
464 /// is_integral
465 template<typename _Tp>
466 struct is_integral
467 : public __is_integral_helper<__remove_cv_t<_Tp>>::type
468 { };
469
470 /// @cond undocumented
471 template<typename>
472 struct __is_floating_point_helper
473 : public false_type { };
474
475 template<>
476 struct __is_floating_point_helper<float>
477 : public true_type { };
478
479 template<>
480 struct __is_floating_point_helper<double>
481 : public true_type { };
482
483 template<>
484 struct __is_floating_point_helper<long double>
485 : public true_type { };
486
487#ifdef __STDCPP_FLOAT16_T__
488 template<>
489 struct __is_floating_point_helper<_Float16>
490 : public true_type { };
491#endif
492
493#ifdef __STDCPP_FLOAT32_T__
494 template<>
495 struct __is_floating_point_helper<_Float32>
496 : public true_type { };
497#endif
498
499#ifdef __STDCPP_FLOAT64_T__
500 template<>
501 struct __is_floating_point_helper<_Float64>
502 : public true_type { };
503#endif
504
505#ifdef __STDCPP_FLOAT128_T__
506 template<>
507 struct __is_floating_point_helper<_Float128>
508 : public true_type { };
509#endif
510
511#ifdef __STDCPP_BFLOAT16_T__
512 template<>
513 struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t>
514 : public true_type { };
515#endif
516
517#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) && !defined(__CUDACC__)
518 template<>
519 struct __is_floating_point_helper<__float128>
520 : public true_type { };
521#endif
522 /// @endcond
523
524 /// is_floating_point
525 template<typename _Tp>
526 struct is_floating_point
527 : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type
528 { };
529
530 /// is_array
531#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
532 template<typename _Tp>
533 struct is_array
534 : public __bool_constant<__is_array(_Tp)>
535 { };
536#else
537 template<typename>
538 struct is_array
539 : public false_type { };
540
541 template<typename _Tp, std::size_t _Size>
542 struct is_array<_Tp[_Size]>
543 : public true_type { };
544
545 template<typename _Tp>
546 struct is_array<_Tp[]>
547 : public true_type { };
548#endif
549
550 /// is_pointer
551#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer)
552 template<typename _Tp>
553 struct is_pointer
554 : public __bool_constant<__is_pointer(_Tp)>
555 { };
556#else
557 template<typename _Tp>
558 struct is_pointer
559 : public false_type { };
560
561 template<typename _Tp>
562 struct is_pointer<_Tp*>
563 : public true_type { };
564
565 template<typename _Tp>
566 struct is_pointer<_Tp* const>
567 : public true_type { };
568
569 template<typename _Tp>
570 struct is_pointer<_Tp* volatile>
571 : public true_type { };
572
573 template<typename _Tp>
574 struct is_pointer<_Tp* const volatile>
575 : public true_type { };
576#endif
577
578 /// is_lvalue_reference
579 template<typename>
580 struct is_lvalue_reference
581 : public false_type { };
582
583 template<typename _Tp>
584 struct is_lvalue_reference<_Tp&>
585 : public true_type { };
586
587 /// is_rvalue_reference
588 template<typename>
589 struct is_rvalue_reference
590 : public false_type { };
591
592 template<typename _Tp>
593 struct is_rvalue_reference<_Tp&&>
594 : public true_type { };
595
596 /// is_member_object_pointer
597#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
598 template<typename _Tp>
599 struct is_member_object_pointer
600 : public __bool_constant<__is_member_object_pointer(_Tp)>
601 { };
602#else
603 template<typename>
604 struct __is_member_object_pointer_helper
605 : public false_type { };
606
607 template<typename _Tp, typename _Cp>
608 struct __is_member_object_pointer_helper<_Tp _Cp::*>
609 : public __not_<is_function<_Tp>>::type { };
610
611
612 template<typename _Tp>
613 struct is_member_object_pointer
614 : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type
615 { };
616#endif
617
618#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
619 /// is_member_function_pointer
620 template<typename _Tp>
621 struct is_member_function_pointer
622 : public __bool_constant<__is_member_function_pointer(_Tp)>
623 { };
624#else
625 template<typename>
626 struct __is_member_function_pointer_helper
627 : public false_type { };
628
629 template<typename _Tp, typename _Cp>
630 struct __is_member_function_pointer_helper<_Tp _Cp::*>
631 : public is_function<_Tp>::type { };
632
633 /// is_member_function_pointer
634 template<typename _Tp>
635 struct is_member_function_pointer
636 : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type
637 { };
638#endif
639
640 /// is_enum
641 template<typename _Tp>
642 struct is_enum
643 : public __bool_constant<__is_enum(_Tp)>
644 { };
645
646 /// is_union
647 template<typename _Tp>
648 struct is_union
649 : public __bool_constant<__is_union(_Tp)>
650 { };
651
652 /// is_class
653 template<typename _Tp>
654 struct is_class
655 : public __bool_constant<__is_class(_Tp)>
656 { };
657
658 /// is_function
659#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
660 template<typename _Tp>
661 struct is_function
662 : public __bool_constant<__is_function(_Tp)>
663 { };
664#else
665 template<typename _Tp>
666 struct is_function
667 : public __bool_constant<!is_const<const _Tp>::value> { };
668
669 template<typename _Tp>
670 struct is_function<_Tp&>
671 : public false_type { };
672
673 template<typename _Tp>
674 struct is_function<_Tp&&>
675 : public false_type { };
676#endif
677
678#ifdef __cpp_lib_is_null_pointer // C++ >= 11
679 /// is_null_pointer (LWG 2247).
680 template<typename _Tp>
681 struct is_null_pointer
682 : public false_type { };
683
684 template<>
685 struct is_null_pointer<std::nullptr_t>
686 : public true_type { };
687
688 template<>
689 struct is_null_pointer<const std::nullptr_t>
690 : public true_type { };
691
692 template<>
693 struct is_null_pointer<volatile std::nullptr_t>
694 : public true_type { };
695
696 template<>
697 struct is_null_pointer<const volatile std::nullptr_t>
698 : public true_type { };
699
700 /// __is_nullptr_t (deprecated extension).
701 /// @deprecated Non-standard. Use `is_null_pointer` instead.
702 template<typename _Tp>
703 struct __is_nullptr_t
704 : public is_null_pointer<_Tp>
705 { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer");
706#endif // __cpp_lib_is_null_pointer
707
708 // Composite type categories.
709
710 /// is_reference
711#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
712 template<typename _Tp>
713 struct is_reference
714 : public __bool_constant<__is_reference(_Tp)>
715 { };
716#else
717 template<typename _Tp>
718 struct is_reference
719 : public false_type
720 { };
721
722 template<typename _Tp>
723 struct is_reference<_Tp&>
724 : public true_type
725 { };
726
727 template<typename _Tp>
728 struct is_reference<_Tp&&>
729 : public true_type
730 { };
731#endif
732
733 /// is_arithmetic
734 template<typename _Tp>
735 struct is_arithmetic
736 : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type
737 { };
738
739 /// is_fundamental
740 template<typename _Tp>
741 struct is_fundamental
742 : public __or_<is_arithmetic<_Tp>, is_void<_Tp>,
743 is_null_pointer<_Tp>>::type
744 { };
745
746 /// is_object
747#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object)
748 template<typename _Tp>
749 struct is_object
750 : public __bool_constant<__is_object(_Tp)>
751 { };
752#else
753 template<typename _Tp>
754 struct is_object
755 : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
756 is_void<_Tp>>>::type
757 { };
758#endif
759
760 template<typename>
761 struct is_member_pointer;
762
763 /// is_scalar
764 template<typename _Tp>
765 struct is_scalar
766 : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>,
767 is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
768 { };
769
770 /// is_compound
771 template<typename _Tp>
772 struct is_compound
773 : public __bool_constant<!is_fundamental<_Tp>::value> { };
774
775 /// is_member_pointer
776#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
777 template<typename _Tp>
778 struct is_member_pointer
779 : public __bool_constant<__is_member_pointer(_Tp)>
780 { };
781#else
782 /// @cond undocumented
783 template<typename _Tp>
784 struct __is_member_pointer_helper
785 : public false_type { };
786
787 template<typename _Tp, typename _Cp>
788 struct __is_member_pointer_helper<_Tp _Cp::*>
789 : public true_type { };
790 /// @endcond
791
792 template<typename _Tp>
793 struct is_member_pointer
794 : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type
795 { };
796#endif
797
798 template<typename, typename>
799 struct is_same;
800
801 /// @cond undocumented
802 template<typename _Tp, typename... _Types>
803 using __is_one_of = __or_<is_same<_Tp, _Types>...>;
804
805 // Check if a type is one of the signed integer types.
806 __extension__
807 template<typename _Tp>
808 using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
809 signed char, signed short, signed int, signed long,
810 signed long long
811#if defined(__GLIBCXX_TYPE_INT_N_0)
812 , signed __GLIBCXX_TYPE_INT_N_0
813#endif
814#if defined(__GLIBCXX_TYPE_INT_N_1)
815 , signed __GLIBCXX_TYPE_INT_N_1
816#endif
817#if defined(__GLIBCXX_TYPE_INT_N_2)
818 , signed __GLIBCXX_TYPE_INT_N_2
819#endif
820#if defined(__GLIBCXX_TYPE_INT_N_3)
821 , signed __GLIBCXX_TYPE_INT_N_3
822#endif
823 >;
824
825 // Check if a type is one of the unsigned integer types.
826 __extension__
827 template<typename _Tp>
828 using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
829 unsigned char, unsigned short, unsigned int, unsigned long,
830 unsigned long long
831#if defined(__GLIBCXX_TYPE_INT_N_0)
832 , unsigned __GLIBCXX_TYPE_INT_N_0
833#endif
834#if defined(__GLIBCXX_TYPE_INT_N_1)
835 , unsigned __GLIBCXX_TYPE_INT_N_1
836#endif
837#if defined(__GLIBCXX_TYPE_INT_N_2)
838 , unsigned __GLIBCXX_TYPE_INT_N_2
839#endif
840#if defined(__GLIBCXX_TYPE_INT_N_3)
841 , unsigned __GLIBCXX_TYPE_INT_N_3
842#endif
843 >;
844
845 // Check if a type is one of the signed or unsigned integer types.
846 template<typename _Tp>
847 using __is_standard_integer
848 = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
849
850 // __void_t (std::void_t for C++11)
851 template<typename...> using __void_t = void;
852 /// @endcond
853
854 // Type properties.
855
856 /// is_const
857#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const)
858 template<typename _Tp>
859 struct is_const
860 : public __bool_constant<__is_const(_Tp)>
861 { };
862#else
863 template<typename>
864 struct is_const
865 : public false_type { };
866
867 template<typename _Tp>
868 struct is_const<_Tp const>
869 : public true_type { };
870#endif
871
872 /// is_volatile
873#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile)
874 template<typename _Tp>
875 struct is_volatile
876 : public __bool_constant<__is_volatile(_Tp)>
877 { };
878#else
879 template<typename>
880 struct is_volatile
881 : public false_type { };
882
883 template<typename _Tp>
884 struct is_volatile<_Tp volatile>
885 : public true_type { };
886#endif
887
888 /** is_trivial
889 * @deprecated Deprecated in C++26.
890 * Use a combination of one or more more specialized type traits instead,
891 * such as `is_trivially_default_constructible`,
892 * `is_trivially_copy_constructible`, `is_trivially_copy_assignable`,
893 * etc., depending on the exact check(s) needed.
894 */
895 template<typename _Tp>
896 struct
897 _GLIBCXX26_DEPRECATED_SUGGEST("is_trivially_default_constructible && is_trivially_copyable")
898 is_trivial
899 : public __bool_constant<__is_trivial(_Tp)>
900 {
901 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
902 "template argument must be a complete class or an unbounded array");
903 };
904
905 /// is_trivially_copyable
906 template<typename _Tp>
907 struct is_trivially_copyable
908 : public __bool_constant<__is_trivially_copyable(_Tp)>
909 {
910 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
911 "template argument must be a complete class or an unbounded array");
912 };
913
914 /// is_standard_layout
915 template<typename _Tp>
916 struct is_standard_layout
917 : public __bool_constant<__is_standard_layout(_Tp)>
918 {
919 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
920 "template argument must be a complete class or an unbounded array");
921 };
922
923 /** is_pod
924 * @deprecated Deprecated in C++20.
925 * Use `is_standard_layout && is_trivial` instead.
926 */
927 // Could use is_standard_layout && is_trivial instead of the builtin.
928 template<typename _Tp>
929 struct
930 _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial")
931 is_pod
932 : public __bool_constant<__is_pod(_Tp)>
933 {
934 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
935 "template argument must be a complete class or an unbounded array");
936 };
937
938 /** is_literal_type
939 * @deprecated Deprecated in C++17, removed in C++20.
940 * The idea of a literal type isn't useful.
941 */
942 template<typename _Tp>
943 struct
944 _GLIBCXX17_DEPRECATED
945 is_literal_type
946 : public __bool_constant<__is_literal_type(_Tp)>
947 {
948 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
949 "template argument must be a complete class or an unbounded array");
950 };
951
952 /// is_empty
953 template<typename _Tp>
954 struct is_empty
955 : public __bool_constant<__is_empty(_Tp)>
956 { };
957
958 /// is_polymorphic
959 template<typename _Tp>
960 struct is_polymorphic
961 : public __bool_constant<__is_polymorphic(_Tp)>
962 { };
963
964#ifdef __cpp_lib_is_final // C++ >= 14
965 /// is_final
966 /// @since C++14
967 template<typename _Tp>
968 struct is_final
969 : public __bool_constant<__is_final(_Tp)>
970 { };
971#endif
972
973 /// is_abstract
974 template<typename _Tp>
975 struct is_abstract
976 : public __bool_constant<__is_abstract(_Tp)>
977 { };
978
979 /// @cond undocumented
980 template<typename _Tp,
981 bool = is_arithmetic<_Tp>::value>
982 struct __is_signed_helper
983 : public false_type { };
984
985 template<typename _Tp>
986 struct __is_signed_helper<_Tp, true>
987 : public __bool_constant<_Tp(-1) < _Tp(0)>
988 { };
989 /// @endcond
990
991 /// is_signed
992 template<typename _Tp>
993 struct is_signed
994 : public __is_signed_helper<_Tp>::type
995 { };
996
997 /// is_unsigned
998 template<typename _Tp>
999 struct is_unsigned
1000 : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
1001 { };
1002
1003 /// @cond undocumented
1004 template<typename _Tp, typename _Up = _Tp&&>
1005 _Up
1006 __declval(int);
1007
1008 template<typename _Tp>
1009 _Tp
1010 __declval(long);
1011 /// @endcond
1012
1013 template<typename _Tp>
1014 auto declval() noexcept -> decltype(__declval<_Tp>(0));
1015
1016 template<typename>
1017 struct remove_all_extents;
1018
1019 /// @cond undocumented
1020 template<typename _Tp>
1021 struct __is_array_known_bounds
1022 : public false_type
1023 { };
1024
1025 template<typename _Tp, size_t _Size>
1026 struct __is_array_known_bounds<_Tp[_Size]>
1027 : public true_type
1028 { };
1029
1030 template<typename _Tp>
1031 struct __is_array_unknown_bounds
1032 : public false_type
1033 { };
1034
1035 template<typename _Tp>
1036 struct __is_array_unknown_bounds<_Tp[]>
1037 : public true_type
1038 { };
1039
1040 // Destructible and constructible type properties.
1041
1042 // In N3290 is_destructible does not say anything about function
1043 // types and abstract types, see LWG 2049. This implementation
1044 // describes function types as non-destructible and all complete
1045 // object types as destructible, iff the explicit destructor
1046 // call expression is wellformed.
1047 struct __do_is_destructible_impl
1048 {
1049 template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())>
1050 static true_type __test(int);
1051
1052 template<typename>
1053 static false_type __test(...);
1054 };
1055
1056 template<typename _Tp>
1057 struct __is_destructible_impl
1058 : public __do_is_destructible_impl
1059 {
1060 using type = decltype(__test<_Tp>(0));
1061 };
1062
1063 template<typename _Tp,
1064 bool = __or_<is_void<_Tp>,
1065 __is_array_unknown_bounds<_Tp>,
1066 is_function<_Tp>>::value,
1067 bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value>
1068 struct __is_destructible_safe;
1069
1070 template<typename _Tp>
1071 struct __is_destructible_safe<_Tp, false, false>
1072 : public __is_destructible_impl<typename
1073 remove_all_extents<_Tp>::type>::type
1074 { };
1075
1076 template<typename _Tp>
1077 struct __is_destructible_safe<_Tp, true, false>
1078 : public false_type { };
1079
1080 template<typename _Tp>
1081 struct __is_destructible_safe<_Tp, false, true>
1082 : public true_type { };
1083 /// @endcond
1084
1085 /// is_destructible
1086 template<typename _Tp>
1087 struct is_destructible
1088 : public __is_destructible_safe<_Tp>::type
1089 {
1090 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1091 "template argument must be a complete class or an unbounded array");
1092 };
1093
1094 /// @cond undocumented
1095
1096 // is_nothrow_destructible requires that is_destructible is
1097 // satisfied as well. We realize that by mimicing the
1098 // implementation of is_destructible but refer to noexcept(expr)
1099 // instead of decltype(expr).
1100 struct __do_is_nt_destructible_impl
1101 {
1102 template<typename _Tp>
1103 static __bool_constant<noexcept(declval<_Tp&>().~_Tp())>
1104 __test(int);
1105
1106 template<typename>
1107 static false_type __test(...);
1108 };
1109
1110 template<typename _Tp>
1111 struct __is_nt_destructible_impl
1112 : public __do_is_nt_destructible_impl
1113 {
1114 using type = decltype(__test<_Tp>(0));
1115 };
1116
1117 template<typename _Tp,
1118 bool = __or_<is_void<_Tp>,
1119 __is_array_unknown_bounds<_Tp>,
1120 is_function<_Tp>>::value,
1121 bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value>
1122 struct __is_nt_destructible_safe;
1123
1124 template<typename _Tp>
1125 struct __is_nt_destructible_safe<_Tp, false, false>
1126 : public __is_nt_destructible_impl<typename
1127 remove_all_extents<_Tp>::type>::type
1128 { };
1129
1130 template<typename _Tp>
1131 struct __is_nt_destructible_safe<_Tp, true, false>
1132 : public false_type { };
1133
1134 template<typename _Tp>
1135 struct __is_nt_destructible_safe<_Tp, false, true>
1136 : public true_type { };
1137 /// @endcond
1138
1139 /// is_nothrow_destructible
1140 template<typename _Tp>
1141 struct is_nothrow_destructible
1142 : public __is_nt_destructible_safe<_Tp>::type
1143 {
1144 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1145 "template argument must be a complete class or an unbounded array");
1146 };
1147
1148 /// @cond undocumented
1149 template<typename _Tp, typename... _Args>
1150 using __is_constructible_impl
1151 = __bool_constant<__is_constructible(_Tp, _Args...)>;
1152 /// @endcond
1153
1154 /// is_constructible
1155 template<typename _Tp, typename... _Args>
1156 struct is_constructible
1157 : public __is_constructible_impl<_Tp, _Args...>
1158 {
1159 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1160 "template argument must be a complete class or an unbounded array");
1161 };
1162
1163 /// is_default_constructible
1164 template<typename _Tp>
1165 struct is_default_constructible
1166 : public __is_constructible_impl<_Tp>
1167 {
1168 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1169 "template argument must be a complete class or an unbounded array");
1170 };
1171
1172 /// @cond undocumented
1173#if _GLIBCXX_USE_BUILTIN_TRAIT(__add_lvalue_reference)
1174 template<typename _Tp>
1175 using __add_lval_ref_t = __add_lvalue_reference(_Tp);
1176#else
1177 template<typename _Tp, typename = void>
1178 struct __add_lvalue_reference_helper
1179 { using type = _Tp; };
1180
1181 template<typename _Tp>
1182 struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>>
1183 { using type = _Tp&; };
1184
1185 template<typename _Tp>
1186 using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type;
1187#endif
1188 /// @endcond
1189
1190 /// is_copy_constructible
1191 template<typename _Tp>
1192 struct is_copy_constructible
1193 : public __is_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
1194 {
1195 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1196 "template argument must be a complete class or an unbounded array");
1197 };
1198
1199 /// @cond undocumented
1200#if _GLIBCXX_USE_BUILTIN_TRAIT(__add_rvalue_reference)
1201 template<typename _Tp>
1202 using __add_rval_ref_t = __add_rvalue_reference(_Tp);
1203#else
1204 template<typename _Tp, typename = void>
1205 struct __add_rvalue_reference_helper
1206 { using type = _Tp; };
1207
1208 template<typename _Tp>
1209 struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>>
1210 { using type = _Tp&&; };
1211
1212 template<typename _Tp>
1213 using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type;
1214#endif
1215 /// @endcond
1216
1217 /// is_move_constructible
1218 template<typename _Tp>
1219 struct is_move_constructible
1220 : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
1221 {
1222 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1223 "template argument must be a complete class or an unbounded array");
1224 };
1225
1226 /// @cond undocumented
1227 template<typename _Tp, typename... _Args>
1228 using __is_nothrow_constructible_impl
1229 = __bool_constant<__is_nothrow_constructible(_Tp, _Args...)>;
1230 /// @endcond
1231
1232 /// is_nothrow_constructible
1233 template<typename _Tp, typename... _Args>
1234 struct is_nothrow_constructible
1235 : public __is_nothrow_constructible_impl<_Tp, _Args...>
1236 {
1237 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1238 "template argument must be a complete class or an unbounded array");
1239 };
1240
1241 /// is_nothrow_default_constructible
1242 template<typename _Tp>
1243 struct is_nothrow_default_constructible
1244 : public __is_nothrow_constructible_impl<_Tp>
1245 {
1246 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1247 "template argument must be a complete class or an unbounded array");
1248 };
1249
1250 /// is_nothrow_copy_constructible
1251 template<typename _Tp>
1252 struct is_nothrow_copy_constructible
1253 : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
1254 {
1255 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1256 "template argument must be a complete class or an unbounded array");
1257 };
1258
1259 /// is_nothrow_move_constructible
1260 template<typename _Tp>
1261 struct is_nothrow_move_constructible
1262 : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
1263 {
1264 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1265 "template argument must be a complete class or an unbounded array");
1266 };
1267
1268 /// @cond undocumented
1269 template<typename _Tp, typename _Up>
1270 using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>;
1271 /// @endcond
1272
1273 /// is_assignable
1274 template<typename _Tp, typename _Up>
1275 struct is_assignable
1276 : public __is_assignable_impl<_Tp, _Up>
1277 {
1278 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1279 "template argument must be a complete class or an unbounded array");
1280 };
1281
1282 /// is_copy_assignable
1283 template<typename _Tp>
1284 struct is_copy_assignable
1285 : public __is_assignable_impl<__add_lval_ref_t<_Tp>,
1286 __add_lval_ref_t<const _Tp>>
1287 {
1288 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1289 "template argument must be a complete class or an unbounded array");
1290 };
1291
1292 /// is_move_assignable
1293 template<typename _Tp>
1294 struct is_move_assignable
1295 : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>>
1296 {
1297 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1298 "template argument must be a complete class or an unbounded array");
1299 };
1300
1301 /// @cond undocumented
1302 template<typename _Tp, typename _Up>
1303 using __is_nothrow_assignable_impl
1304 = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>;
1305 /// @endcond
1306
1307 /// is_nothrow_assignable
1308 template<typename _Tp, typename _Up>
1309 struct is_nothrow_assignable
1310 : public __is_nothrow_assignable_impl<_Tp, _Up>
1311 {
1312 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1313 "template argument must be a complete class or an unbounded array");
1314 };
1315
1316 /// is_nothrow_copy_assignable
1317 template<typename _Tp>
1318 struct is_nothrow_copy_assignable
1319 : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
1320 __add_lval_ref_t<const _Tp>>
1321 {
1322 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1323 "template argument must be a complete class or an unbounded array");
1324 };
1325
1326 /// is_nothrow_move_assignable
1327 template<typename _Tp>
1328 struct is_nothrow_move_assignable
1329 : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
1330 __add_rval_ref_t<_Tp>>
1331 {
1332 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1333 "template argument must be a complete class or an unbounded array");
1334 };
1335
1336 /// @cond undocumented
1337 template<typename _Tp, typename... _Args>
1338 using __is_trivially_constructible_impl
1339 = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>;
1340 /// @endcond
1341
1342 /// is_trivially_constructible
1343 template<typename _Tp, typename... _Args>
1344 struct is_trivially_constructible
1345 : public __is_trivially_constructible_impl<_Tp, _Args...>
1346 {
1347 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1348 "template argument must be a complete class or an unbounded array");
1349 };
1350
1351 /// is_trivially_default_constructible
1352 template<typename _Tp>
1353 struct is_trivially_default_constructible
1354 : public __is_trivially_constructible_impl<_Tp>
1355 {
1356 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1357 "template argument must be a complete class or an unbounded array");
1358 };
1359
1360#if __cpp_variable_templates && __cpp_concepts
1361 template<typename _Tp>
1362 constexpr bool __is_implicitly_default_constructible_v
1363 = requires (void(&__f)(_Tp)) { __f({}); };
1364
1365 template<typename _Tp>
1366 struct __is_implicitly_default_constructible
1367 : __bool_constant<__is_implicitly_default_constructible_v<_Tp>>
1368 { };
1369#else
1370 struct __do_is_implicitly_default_constructible_impl
1371 {
1372 template <typename _Tp>
1373 static void __helper(const _Tp&);
1374
1375 template <typename _Tp>
1376 static true_type __test(const _Tp&,
1377 decltype(__helper<const _Tp&>({}))* = 0);
1378
1379 static false_type __test(...);
1380 };
1381
1382 template<typename _Tp>
1383 struct __is_implicitly_default_constructible_impl
1384 : public __do_is_implicitly_default_constructible_impl
1385 {
1386 using type = decltype(__test(declval<_Tp>()));
1387 };
1388
1389 template<typename _Tp>
1390 struct __is_implicitly_default_constructible_safe
1391 : public __is_implicitly_default_constructible_impl<_Tp>::type
1392 { };
1393
1394 template <typename _Tp>
1395 struct __is_implicitly_default_constructible
1396 : public __and_<__is_constructible_impl<_Tp>,
1397 __is_implicitly_default_constructible_safe<_Tp>>::type
1398 { };
1399#endif
1400
1401 /// is_trivially_copy_constructible
1402 template<typename _Tp>
1403 struct is_trivially_copy_constructible
1404 : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
1405 {
1406 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1407 "template argument must be a complete class or an unbounded array");
1408 };
1409
1410 /// is_trivially_move_constructible
1411 template<typename _Tp>
1412 struct is_trivially_move_constructible
1413 : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
1414 {
1415 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1416 "template argument must be a complete class or an unbounded array");
1417 };
1418
1419 /// @cond undocumented
1420 template<typename _Tp, typename _Up>
1421 using __is_trivially_assignable_impl
1422 = __bool_constant<__is_trivially_assignable(_Tp, _Up)>;
1423 /// @endcond
1424
1425 /// is_trivially_assignable
1426 template<typename _Tp, typename _Up>
1427 struct is_trivially_assignable
1428 : public __is_trivially_assignable_impl<_Tp, _Up>
1429 {
1430 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1431 "template argument must be a complete class or an unbounded array");
1432 };
1433
1434 /// is_trivially_copy_assignable
1435 template<typename _Tp>
1436 struct is_trivially_copy_assignable
1437 : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
1438 __add_lval_ref_t<const _Tp>>
1439 {
1440 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1441 "template argument must be a complete class or an unbounded array");
1442 };
1443
1444 /// is_trivially_move_assignable
1445 template<typename _Tp>
1446 struct is_trivially_move_assignable
1447 : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
1448 __add_rval_ref_t<_Tp>>
1449 {
1450 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1451 "template argument must be a complete class or an unbounded array");
1452 };
1453
1454 /// is_trivially_destructible
1455 template<typename _Tp>
1456 struct is_trivially_destructible
1457 : public __and_<__is_destructible_safe<_Tp>,
1458 __bool_constant<__has_trivial_destructor(_Tp)>>::type
1459 {
1460 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1461 "template argument must be a complete class or an unbounded array");
1462 };
1463
1464
1465 /// has_virtual_destructor
1466 template<typename _Tp>
1467 struct has_virtual_destructor
1468 : public __bool_constant<__has_virtual_destructor(_Tp)>
1469 {
1470 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1471 "template argument must be a complete class or an unbounded array");
1472 };
1473
1474
1475 // type property queries.
1476
1477 /// alignment_of
1478 template<typename _Tp>
1479 struct alignment_of
1480 : public integral_constant<std::size_t, alignof(_Tp)>
1481 {
1482 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1483 "template argument must be a complete class or an unbounded array");
1484 };
1485
1486 /// rank
1487#if _GLIBCXX_USE_BUILTIN_TRAIT(__array_rank) \
1488 && (!defined(__clang__) || __clang_major__ >= 20) // PR118559
1489 template<typename _Tp>
1490 struct rank
1491 : public integral_constant<std::size_t, __array_rank(_Tp)> { };
1492#else
1493 template<typename>
1494 struct rank
1495 : public integral_constant<std::size_t, 0> { };
1496
1497 template<typename _Tp, std::size_t _Size>
1498 struct rank<_Tp[_Size]>
1499 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
1500
1501 template<typename _Tp>
1502 struct rank<_Tp[]>
1503 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
1504#endif
1505
1506 /// extent
1507 template<typename, unsigned _Uint = 0>
1508 struct extent
1509 : public integral_constant<size_t, 0> { };
1510
1511 template<typename _Tp, size_t _Size>
1512 struct extent<_Tp[_Size], 0>
1513 : public integral_constant<size_t, _Size> { };
1514
1515 template<typename _Tp, unsigned _Uint, size_t _Size>
1516 struct extent<_Tp[_Size], _Uint>
1517 : public extent<_Tp, _Uint - 1>::type { };
1518
1519 template<typename _Tp>
1520 struct extent<_Tp[], 0>
1521 : public integral_constant<size_t, 0> { };
1522
1523 template<typename _Tp, unsigned _Uint>
1524 struct extent<_Tp[], _Uint>
1525 : public extent<_Tp, _Uint - 1>::type { };
1526
1527
1528 // Type relations.
1529
1530 /// is_same
1531#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same)
1532 template<typename _Tp, typename _Up>
1533 struct is_same
1534 : public __bool_constant<__is_same(_Tp, _Up)>
1535 { };
1536#else
1537 template<typename _Tp, typename _Up>
1538 struct is_same
1539 : public false_type
1540 { };
1541
1542 template<typename _Tp>
1543 struct is_same<_Tp, _Tp>
1544 : public true_type
1545 { };
1546#endif
1547
1548 /// is_base_of
1549 template<typename _Base, typename _Derived>
1550 struct is_base_of
1551 : public __bool_constant<__is_base_of(_Base, _Derived)>
1552 { };
1553
1554#ifdef __cpp_lib_is_virtual_base_of // C++ >= 26
1555 /// is_virtual_base_of
1556 /// @since C++26
1557 template<typename _Base, typename _Derived>
1558 struct is_virtual_base_of
1559 : public bool_constant<__builtin_is_virtual_base_of(_Base, _Derived)>
1560 { };
1561#endif
1562
1563#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible)
1564 template<typename _From, typename _To>
1565 struct is_convertible
1566 : public __bool_constant<__is_convertible(_From, _To)>
1567 { };
1568#else
1569 template<typename _From, typename _To,
1570 bool = __or_<is_void<_From>, is_function<_To>,
1571 is_array<_To>>::value>
1572 struct __is_convertible_helper
1573 {
1574 using type = typename is_void<_To>::type;
1575 };
1576
1577#pragma GCC diagnostic push
1578#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
1579 template<typename _From, typename _To>
1580 class __is_convertible_helper<_From, _To, false>
1581 {
1582 template<typename _To1>
1583 static void __test_aux(_To1) noexcept;
1584
1585 template<typename _From1, typename _To1,
1586 typename = decltype(__test_aux<_To1>(std::declval<_From1>()))>
1587 static true_type
1588 __test(int);
1589
1590 template<typename, typename>
1591 static false_type
1592 __test(...);
1593
1594 public:
1595 using type = decltype(__test<_From, _To>(0));
1596 };
1597#pragma GCC diagnostic pop
1598
1599 /// is_convertible
1600 template<typename _From, typename _To>
1601 struct is_convertible
1602 : public __is_convertible_helper<_From, _To>::type
1603 { };
1604#endif
1605
1606 // helper trait for unique_ptr<T[]>, shared_ptr<T[]>, and span<T, N>
1607 template<typename _ToElementType, typename _FromElementType>
1608 using __is_array_convertible
1609 = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>;
1610
1611#ifdef __cpp_lib_is_nothrow_convertible // C++ >= 20
1612
1613#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_convertible)
1614 /// is_nothrow_convertible_v
1615 template<typename _From, typename _To>
1616 inline constexpr bool is_nothrow_convertible_v
1617 = __is_nothrow_convertible(_From, _To);
1618
1619 /// is_nothrow_convertible
1620 template<typename _From, typename _To>
1621 struct is_nothrow_convertible
1622 : public bool_constant<is_nothrow_convertible_v<_From, _To>>
1623 { };
1624#else
1625 template<typename _From, typename _To,
1626 bool = __or_<is_void<_From>, is_function<_To>,
1627 is_array<_To>>::value>
1628 struct __is_nt_convertible_helper
1629 : is_void<_To>
1630 { };
1631
1632#pragma GCC diagnostic push
1633#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
1634 template<typename _From, typename _To>
1635 class __is_nt_convertible_helper<_From, _To, false>
1636 {
1637 template<typename _To1>
1638 static void __test_aux(_To1) noexcept;
1639
1640 template<typename _From1, typename _To1>
1641 static
1642 __bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))>
1643 __test(int);
1644
1645 template<typename, typename>
1646 static false_type
1647 __test(...);
1648
1649 public:
1650 using type = decltype(__test<_From, _To>(0));
1651 };
1652#pragma GCC diagnostic pop
1653
1654 /// is_nothrow_convertible
1655 template<typename _From, typename _To>
1656 struct is_nothrow_convertible
1657 : public __is_nt_convertible_helper<_From, _To>::type
1658 { };
1659
1660 /// is_nothrow_convertible_v
1661 template<typename _From, typename _To>
1662 inline constexpr bool is_nothrow_convertible_v
1663 = is_nothrow_convertible<_From, _To>::value;
1664#endif
1665#endif // __cpp_lib_is_nothrow_convertible
1666
1667#pragma GCC diagnostic push
1668#pragma GCC diagnostic ignored "-Wc++14-extensions" // for variable templates
1669 template<typename _Tp, typename... _Args>
1670 struct __is_nothrow_new_constructible_impl
1671 : __bool_constant<
1672 noexcept(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))
1673 >
1674 { };
1675
1676 template<typename _Tp, typename... _Args>
1677 _GLIBCXX17_INLINE constexpr bool __is_nothrow_new_constructible
1678 = __and_<is_constructible<_Tp, _Args...>,
1679 __is_nothrow_new_constructible_impl<_Tp, _Args...>>::value;
1680#pragma GCC diagnostic pop
1681
1682 // Const-volatile modifications.
1683
1684 /// remove_const
1685 template<typename _Tp>
1686 struct remove_const
1687 { using type = _Tp; };
1688
1689 template<typename _Tp>
1690 struct remove_const<_Tp const>
1691 { using type = _Tp; };
1692
1693 /// remove_volatile
1694 template<typename _Tp>
1695 struct remove_volatile
1696 { using type = _Tp; };
1697
1698 template<typename _Tp>
1699 struct remove_volatile<_Tp volatile>
1700 { using type = _Tp; };
1701
1702 /// remove_cv
1703#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cv)
1704 template<typename _Tp>
1705 struct remove_cv
1706 { using type = __remove_cv(_Tp); };
1707#else
1708 template<typename _Tp>
1709 struct remove_cv
1710 { using type = _Tp; };
1711
1712 template<typename _Tp>
1713 struct remove_cv<const _Tp>
1714 { using type = _Tp; };
1715
1716 template<typename _Tp>
1717 struct remove_cv<volatile _Tp>
1718 { using type = _Tp; };
1719
1720 template<typename _Tp>
1721 struct remove_cv<const volatile _Tp>
1722 { using type = _Tp; };
1723#endif
1724
1725 /// add_const
1726 template<typename _Tp>
1727 struct add_const
1728 { using type = _Tp const; };
1729
1730 /// add_volatile
1731 template<typename _Tp>
1732 struct add_volatile
1733 { using type = _Tp volatile; };
1734
1735 /// add_cv
1736 template<typename _Tp>
1737 struct add_cv
1738 { using type = _Tp const volatile; };
1739
1740#ifdef __cpp_lib_transformation_trait_aliases // C++ >= 14
1741 /// Alias template for remove_const
1742 template<typename _Tp>
1743 using remove_const_t = typename remove_const<_Tp>::type;
1744
1745 /// Alias template for remove_volatile
1746 template<typename _Tp>
1747 using remove_volatile_t = typename remove_volatile<_Tp>::type;
1748
1749 /// Alias template for remove_cv
1750 template<typename _Tp>
1751 using remove_cv_t = typename remove_cv<_Tp>::type;
1752
1753 /// Alias template for add_const
1754 template<typename _Tp>
1755 using add_const_t = typename add_const<_Tp>::type;
1756
1757 /// Alias template for add_volatile
1758 template<typename _Tp>
1759 using add_volatile_t = typename add_volatile<_Tp>::type;
1760
1761 /// Alias template for add_cv
1762 template<typename _Tp>
1763 using add_cv_t = typename add_cv<_Tp>::type;
1764#endif
1765
1766 // Reference transformations.
1767
1768 /// remove_reference
1769#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_reference)
1770 template<typename _Tp>
1771 struct remove_reference
1772 { using type = __remove_reference(_Tp); };
1773#else
1774 template<typename _Tp>
1775 struct remove_reference
1776 { using type = _Tp; };
1777
1778 template<typename _Tp>
1779 struct remove_reference<_Tp&>
1780 { using type = _Tp; };
1781
1782 template<typename _Tp>
1783 struct remove_reference<_Tp&&>
1784 { using type = _Tp; };
1785#endif
1786
1787 /// add_lvalue_reference
1788 template<typename _Tp>
1789 struct add_lvalue_reference
1790 { using type = __add_lval_ref_t<_Tp>; };
1791
1792 /// add_rvalue_reference
1793 template<typename _Tp>
1794 struct add_rvalue_reference
1795 { using type = __add_rval_ref_t<_Tp>; };
1796
1797#if __cplusplus > 201103L
1798 /// Alias template for remove_reference
1799 template<typename _Tp>
1800 using remove_reference_t = typename remove_reference<_Tp>::type;
1801
1802 /// Alias template for add_lvalue_reference
1803 template<typename _Tp>
1804 using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;
1805
1806 /// Alias template for add_rvalue_reference
1807 template<typename _Tp>
1808 using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
1809#endif
1810
1811 // Sign modifications.
1812
1813 /// @cond undocumented
1814
1815 // Utility for constructing identically cv-qualified types.
1816 template<typename _Unqualified, bool _IsConst, bool _IsVol>
1817 struct __cv_selector;
1818
1819 template<typename _Unqualified>
1820 struct __cv_selector<_Unqualified, false, false>
1821 { using __type = _Unqualified; };
1822
1823 template<typename _Unqualified>
1824 struct __cv_selector<_Unqualified, false, true>
1825 { using __type = volatile _Unqualified; };
1826
1827 template<typename _Unqualified>
1828 struct __cv_selector<_Unqualified, true, false>
1829 { using __type = const _Unqualified; };
1830
1831 template<typename _Unqualified>
1832 struct __cv_selector<_Unqualified, true, true>
1833 { using __type = const volatile _Unqualified; };
1834
1835 template<typename _Qualified, typename _Unqualified,
1836 bool _IsConst = is_const<_Qualified>::value,
1837 bool _IsVol = is_volatile<_Qualified>::value>
1838 class __match_cv_qualifiers
1839 {
1840 using __match = __cv_selector<_Unqualified, _IsConst, _IsVol>;
1841
1842 public:
1843 using __type = typename __match::__type;
1844 };
1845
1846 // Utility for finding the unsigned versions of signed integral types.
1847 template<typename _Tp>
1848 struct __make_unsigned
1849 { using __type = _Tp; };
1850
1851 template<>
1852 struct __make_unsigned<char>
1853 { using __type = unsigned char; };
1854
1855 template<>
1856 struct __make_unsigned<signed char>
1857 { using __type = unsigned char; };
1858
1859 template<>
1860 struct __make_unsigned<short>
1861 { using __type = unsigned short; };
1862
1863 template<>
1864 struct __make_unsigned<int>
1865 { using __type = unsigned int; };
1866
1867 template<>
1868 struct __make_unsigned<long>
1869 { using __type = unsigned long; };
1870
1871 template<>
1872 struct __make_unsigned<long long>
1873 { using __type = unsigned long long; };
1874
1875#if defined(__GLIBCXX_TYPE_INT_N_0)
1876 __extension__
1877 template<>
1878 struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
1879 { using __type = unsigned __GLIBCXX_TYPE_INT_N_0; };
1880#endif
1881#if defined(__GLIBCXX_TYPE_INT_N_1)
1882 __extension__
1883 template<>
1884 struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1>
1885 { using __type = unsigned __GLIBCXX_TYPE_INT_N_1; };
1886#endif
1887#if defined(__GLIBCXX_TYPE_INT_N_2)
1888 __extension__
1889 template<>
1890 struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2>
1891 { using __type = unsigned __GLIBCXX_TYPE_INT_N_2; };
1892#endif
1893#if defined(__GLIBCXX_TYPE_INT_N_3)
1894 __extension__
1895 template<>
1896 struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
1897 { using __type = unsigned __GLIBCXX_TYPE_INT_N_3; };
1898#endif
1899
1900 // Select between integral and enum: not possible to be both.
1901 template<typename _Tp,
1902 bool _IsInt = is_integral<_Tp>::value,
1903 bool _IsEnum = __is_enum(_Tp)>
1904 class __make_unsigned_selector;
1905
1906 template<typename _Tp>
1907 class __make_unsigned_selector<_Tp, true, false>
1908 {
1909 using __unsigned_type
1910 = typename __make_unsigned<__remove_cv_t<_Tp>>::__type;
1911
1912 public:
1913 using __type
1914 = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type;
1915 };
1916
1917 class __make_unsigned_selector_base
1918 {
1919 protected:
1920 template<typename...> struct _List { };
1921
1922 template<typename _Tp, typename... _Up>
1923 struct _List<_Tp, _Up...> : _List<_Up...>
1924 { static constexpr size_t __size = sizeof(_Tp); };
1925
1926 template<size_t _Sz, typename _Tp, bool = (_Sz <= _Tp::__size)>
1927 struct __select;
1928
1929 template<size_t _Sz, typename _Uint, typename... _UInts>
1930 struct __select<_Sz, _List<_Uint, _UInts...>, true>
1931 { using __type = _Uint; };
1932
1933 template<size_t _Sz, typename _Uint, typename... _UInts>
1934 struct __select<_Sz, _List<_Uint, _UInts...>, false>
1935 : __select<_Sz, _List<_UInts...>>
1936 { };
1937 };
1938
1939 // Choose unsigned integer type with the smallest rank and same size as _Tp
1940 template<typename _Tp>
1941 class __make_unsigned_selector<_Tp, false, true>
1942 : __make_unsigned_selector_base
1943 {
1944 // With -fshort-enums, an enum may be as small as a char.
1945 using _UInts = _List<unsigned char, unsigned short, unsigned int,
1946 unsigned long, unsigned long long>;
1947
1948 using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;
1949
1950 public:
1951 using __type
1952 = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type;
1953 };
1954
1955 // wchar_t, char8_t, char16_t and char32_t are integral types but are
1956 // neither signed integer types nor unsigned integer types, so must be
1957 // transformed to the unsigned integer type with the smallest rank.
1958 // Use the partial specialization for enumeration types to do that.
1959 template<>
1960 struct __make_unsigned<wchar_t>
1961 {
1962 using __type
1963 = typename __make_unsigned_selector<wchar_t, false, true>::__type;
1964 };
1965
1966#ifdef _GLIBCXX_USE_CHAR8_T
1967 template<>
1968 struct __make_unsigned<char8_t>
1969 {
1970 using __type
1971 = typename __make_unsigned_selector<char8_t, false, true>::__type;
1972 };
1973#endif
1974
1975 template<>
1976 struct __make_unsigned<char16_t>
1977 {
1978 using __type
1979 = typename __make_unsigned_selector<char16_t, false, true>::__type;
1980 };
1981
1982 template<>
1983 struct __make_unsigned<char32_t>
1984 {
1985 using __type
1986 = typename __make_unsigned_selector<char32_t, false, true>::__type;
1987 };
1988 /// @endcond
1989
1990 // Given an integral/enum type, return the corresponding unsigned
1991 // integer type.
1992 // Primary template.
1993 /// make_unsigned
1994 template<typename _Tp>
1995 struct make_unsigned
1996 { using type = typename __make_unsigned_selector<_Tp>::__type; };
1997
1998 // Integral, but don't define.
1999 template<> struct make_unsigned<bool>;
2000 template<> struct make_unsigned<bool const>;
2001 template<> struct make_unsigned<bool volatile>;
2002 template<> struct make_unsigned<bool const volatile>;
2003
2004 /// @cond undocumented
2005
2006 // Utility for finding the signed versions of unsigned integral types.
2007 template<typename _Tp>
2008 struct __make_signed
2009 { using __type = _Tp; };
2010
2011 template<>
2012 struct __make_signed<char>
2013 { using __type = signed char; };
2014
2015 template<>
2016 struct __make_signed<unsigned char>
2017 { using __type = signed char; };
2018
2019 template<>
2020 struct __make_signed<unsigned short>
2021 { using __type = signed short; };
2022
2023 template<>
2024 struct __make_signed<unsigned int>
2025 { using __type = signed int; };
2026
2027 template<>
2028 struct __make_signed<unsigned long>
2029 { using __type = signed long; };
2030
2031 template<>
2032 struct __make_signed<unsigned long long>
2033 { using __type = signed long long; };
2034
2035#if defined(__GLIBCXX_TYPE_INT_N_0)
2036 __extension__
2037 template<>
2038 struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
2039 { using __type = __GLIBCXX_TYPE_INT_N_0; };
2040#endif
2041#if defined(__GLIBCXX_TYPE_INT_N_1)
2042 __extension__
2043 template<>
2044 struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_1>
2045 { using __type = __GLIBCXX_TYPE_INT_N_1; };
2046#endif
2047#if defined(__GLIBCXX_TYPE_INT_N_2)
2048 __extension__
2049 template<>
2050 struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_2>
2051 { using __type = __GLIBCXX_TYPE_INT_N_2; };
2052#endif
2053#if defined(__GLIBCXX_TYPE_INT_N_3)
2054 __extension__
2055 template<>
2056 struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
2057 { using __type = __GLIBCXX_TYPE_INT_N_3; };
2058#endif
2059
2060 // Select between integral and enum: not possible to be both.
2061 template<typename _Tp,
2062 bool _IsInt = is_integral<_Tp>::value,
2063 bool _IsEnum = __is_enum(_Tp)>
2064 class __make_signed_selector;
2065
2066 template<typename _Tp>
2067 class __make_signed_selector<_Tp, true, false>
2068 {
2069 using __signed_type
2070 = typename __make_signed<__remove_cv_t<_Tp>>::__type;
2071
2072 public:
2073 using __type
2074 = typename __match_cv_qualifiers<_Tp, __signed_type>::__type;
2075 };
2076
2077 // Choose signed integer type with the smallest rank and same size as _Tp
2078 template<typename _Tp>
2079 class __make_signed_selector<_Tp, false, true>
2080 {
2081 using __unsigned_type = typename __make_unsigned_selector<_Tp>::__type;
2082
2083 public:
2084 using __type = typename __make_signed_selector<__unsigned_type>::__type;
2085 };
2086
2087 // wchar_t, char16_t and char32_t are integral types but are neither
2088 // signed integer types nor unsigned integer types, so must be
2089 // transformed to the signed integer type with the smallest rank.
2090 // Use the partial specialization for enumeration types to do that.
2091 template<>
2092 struct __make_signed<wchar_t>
2093 {
2094 using __type
2095 = typename __make_signed_selector<wchar_t, false, true>::__type;
2096 };
2097
2098#if defined(_GLIBCXX_USE_CHAR8_T)
2099 template<>
2100 struct __make_signed<char8_t>
2101 {
2102 using __type
2103 = typename __make_signed_selector<char8_t, false, true>::__type;
2104 };
2105#endif
2106
2107 template<>
2108 struct __make_signed<char16_t>
2109 {
2110 using __type
2111 = typename __make_signed_selector<char16_t, false, true>::__type;
2112 };
2113
2114 template<>
2115 struct __make_signed<char32_t>
2116 {
2117 using __type
2118 = typename __make_signed_selector<char32_t, false, true>::__type;
2119 };
2120 /// @endcond
2121
2122 // Given an integral/enum type, return the corresponding signed
2123 // integer type.
2124 // Primary template.
2125 /// make_signed
2126 template<typename _Tp>
2127 struct make_signed
2128 { using type = typename __make_signed_selector<_Tp>::__type; };
2129
2130 // Integral, but don't define.
2131 template<> struct make_signed<bool>;
2132 template<> struct make_signed<bool const>;
2133 template<> struct make_signed<bool volatile>;
2134 template<> struct make_signed<bool const volatile>;
2135
2136#if __cplusplus > 201103L
2137 /// Alias template for make_signed
2138 template<typename _Tp>
2139 using make_signed_t = typename make_signed<_Tp>::type;
2140
2141 /// Alias template for make_unsigned
2142 template<typename _Tp>
2143 using make_unsigned_t = typename make_unsigned<_Tp>::type;
2144#endif
2145
2146 // Array modifications.
2147
2148 /// remove_extent
2149#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_extent)
2150 template<typename _Tp>
2151 struct remove_extent
2152 { using type = __remove_extent(_Tp); };
2153#else
2154 template<typename _Tp>
2155 struct remove_extent
2156 { using type = _Tp; };
2157
2158 template<typename _Tp, std::size_t _Size>
2159 struct remove_extent<_Tp[_Size]>
2160 { using type = _Tp; };
2161
2162 template<typename _Tp>
2163 struct remove_extent<_Tp[]>
2164 { using type = _Tp; };
2165#endif
2166
2167 /// remove_all_extents
2168#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_all_extents)
2169 template<typename _Tp>
2170 struct remove_all_extents
2171 { using type = __remove_all_extents(_Tp); };
2172#else
2173 template<typename _Tp>
2174 struct remove_all_extents
2175 { using type = _Tp; };
2176
2177 template<typename _Tp, std::size_t _Size>
2178 struct remove_all_extents<_Tp[_Size]>
2179 { using type = typename remove_all_extents<_Tp>::type; };
2180
2181 template<typename _Tp>
2182 struct remove_all_extents<_Tp[]>
2183 { using type = typename remove_all_extents<_Tp>::type; };
2184#endif
2185
2186#if __cplusplus > 201103L
2187 /// Alias template for remove_extent
2188 template<typename _Tp>
2189 using remove_extent_t = typename remove_extent<_Tp>::type;
2190
2191 /// Alias template for remove_all_extents
2192 template<typename _Tp>
2193 using remove_all_extents_t = typename remove_all_extents<_Tp>::type;
2194#endif
2195
2196 // Pointer modifications.
2197
2198 /// remove_pointer
2199#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_pointer)
2200 template<typename _Tp>
2201 struct remove_pointer
2202 { using type = __remove_pointer(_Tp); };
2203#else
2204 template<typename _Tp, typename>
2205 struct __remove_pointer_helper
2206 { using type = _Tp; };
2207
2208 template<typename _Tp, typename _Up>
2209 struct __remove_pointer_helper<_Tp, _Up*>
2210 { using type = _Up; };
2211
2212 template<typename _Tp>
2213 struct remove_pointer
2214 : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>>
2215 { };
2216#endif
2217
2218 /// add_pointer
2219#if _GLIBCXX_USE_BUILTIN_TRAIT(__add_pointer)
2220 template<typename _Tp>
2221 struct add_pointer
2222 { using type = __add_pointer(_Tp); };
2223#else
2224 template<typename _Tp, typename = void>
2225 struct __add_pointer_helper
2226 { using type = _Tp; };
2227
2228 template<typename _Tp>
2229 struct __add_pointer_helper<_Tp, __void_t<_Tp*>>
2230 { using type = _Tp*; };
2231
2232 template<typename _Tp>
2233 struct add_pointer
2234 : public __add_pointer_helper<_Tp>
2235 { };
2236
2237 template<typename _Tp>
2238 struct add_pointer<_Tp&>
2239 { using type = _Tp*; };
2240
2241 template<typename _Tp>
2242 struct add_pointer<_Tp&&>
2243 { using type = _Tp*; };
2244#endif
2245
2246#if __cplusplus > 201103L
2247 /// Alias template for remove_pointer
2248 template<typename _Tp>
2249 using remove_pointer_t = typename remove_pointer<_Tp>::type;
2250
2251 /// Alias template for add_pointer
2252 template<typename _Tp>
2253 using add_pointer_t = typename add_pointer<_Tp>::type;
2254#endif
2255
2256 /// @cond undocumented
2257
2258 // Aligned to maximum fundamental alignment
2259 struct __attribute__((__aligned__)) __aligned_storage_max_align_t
2260 { };
2261
2262 constexpr size_t
2263 __aligned_storage_default_alignment([[__maybe_unused__]] size_t __len)
2264 {
2265#if _GLIBCXX_INLINE_VERSION
2266 using _Max_align
2267 = integral_constant<size_t, alignof(__aligned_storage_max_align_t)>;
2268
2269 return __len > (_Max_align::value / 2)
2270 ? _Max_align::value
2271# if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_clzg)
2272 : 1 << (__SIZE_WIDTH__ - __builtin_clzg(__len - 1u));
2273# else
2274 : 1 << (__LLONG_WIDTH__ - __builtin_clzll(__len - 1ull));
2275# endif
2276#else
2277 // Returning a fixed value is incorrect, but kept for ABI compatibility.
2278 // XXX GLIBCXX_ABI Deprecated
2279 return alignof(__aligned_storage_max_align_t);
2280#endif
2281 }
2282 /// @endcond
2283
2284 /**
2285 * @brief Aligned storage
2286 *
2287 * The member typedef `type` is be a POD type suitable for use as
2288 * uninitialized storage for any object whose size is at most `_Len`
2289 * and whose alignment is a divisor of `_Align`.
2290 *
2291 * It is important to use the nested `type` as uninitialized storage,
2292 * not the `std::aligned_storage` type itself which is an empty class
2293 * with 1-byte alignment. So this is correct:
2294 *
2295 * `typename std::aligned_storage<sizeof(X), alignof(X)>::type m_xobj;`
2296 *
2297 * This is wrong:
2298 *
2299 * `std::aligned_storage<sizeof(X), alignof(X)> m_xobj;`
2300 *
2301 * In C++14 and later `std::aligned_storage_t<sizeof(X), alignof(X)>`
2302 * can be used to refer to the `type` member typedef.
2303 *
2304 * The default value of _Align is supposed to be the most stringent
2305 * fundamental alignment requirement for any C++ object type whose size
2306 * is no greater than `_Len` (see [basic.align] in the C++ standard).
2307 *
2308 * @bug In this implementation the default value for _Align is always the
2309 * maximum fundamental alignment, i.e. `alignof(max_align_t)`, which is
2310 * incorrect. It should be an alignment value no greater than `_Len`.
2311 *
2312 * @deprecated Deprecated in C++23. Uses can be replaced by an
2313 * array `std::byte[_Len]` declared with `alignas(_Align)`.
2314 */
2315 template<size_t _Len,
2316 size_t _Align = __aligned_storage_default_alignment(_Len)>
2317 struct
2318 _GLIBCXX23_DEPRECATED
2319 aligned_storage
2320 {
2321 struct type
2322 {
2323 alignas(_Align) unsigned char __data[_Len];
2324 };
2325 };
2326
2327 template <typename... _Types>
2328 struct __strictest_alignment
2329 {
2330 static const size_t _S_alignment = 0;
2331 static const size_t _S_size = 0;
2332 };
2333
2334 template <typename _Tp, typename... _Types>
2335 struct __strictest_alignment<_Tp, _Types...>
2336 {
2337 static const size_t _S_alignment =
2338 alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment
2339 ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment;
2340 static const size_t _S_size =
2341 sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size
2342 ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size;
2343 };
2344
2345#pragma GCC diagnostic push
2346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2347
2348 /**
2349 * @brief Provide aligned storage for types.
2350 *
2351 * [meta.trans.other]
2352 *
2353 * Provides aligned storage for any of the provided types of at
2354 * least size _Len.
2355 *
2356 * @see aligned_storage
2357 *
2358 * @deprecated Deprecated in C++23.
2359 */
2360 template <size_t _Len, typename... _Types>
2361 struct
2362 _GLIBCXX23_DEPRECATED
2363 aligned_union
2364 {
2365 private:
2366 static_assert(sizeof...(_Types) != 0, "At least one type is required");
2367
2368 using __strictest = __strictest_alignment<_Types...>;
2369 static const size_t _S_len = _Len > __strictest::_S_size
2370 ? _Len : __strictest::_S_size;
2371 public:
2372 /// The value of the strictest alignment of _Types.
2373 static const size_t alignment_value = __strictest::_S_alignment;
2374 /// The storage.
2375 using type = typename aligned_storage<_S_len, alignment_value>::type;
2376 };
2377
2378 template <size_t _Len, typename... _Types>
2379 const size_t aligned_union<_Len, _Types...>::alignment_value;
2380#pragma GCC diagnostic pop
2381
2382 /// @cond undocumented
2383
2384#if _GLIBCXX_USE_BUILTIN_TRAIT(__decay)
2385 template<typename _Tp>
2386 struct decay
2387 { using type = __decay(_Tp); };
2388#else
2389 // Decay trait for arrays and functions, used for perfect forwarding
2390 // in make_pair, make_tuple, etc.
2391 template<typename _Up>
2392 struct __decay_selector
2393 : __conditional_t<is_const<const _Up>::value, // false for functions
2394 remove_cv<_Up>, // N.B. DR 705.
2395 add_pointer<_Up>> // function decays to pointer
2396 { };
2397
2398 template<typename _Up, size_t _Nm>
2399 struct __decay_selector<_Up[_Nm]>
2400 { using type = _Up*; };
2401
2402 template<typename _Up>
2403 struct __decay_selector<_Up[]>
2404 { using type = _Up*; };
2405
2406 /// @endcond
2407
2408 /// decay
2409 template<typename _Tp>
2410 struct decay
2411 { using type = typename __decay_selector<_Tp>::type; };
2412
2413 template<typename _Tp>
2414 struct decay<_Tp&>
2415 { using type = typename __decay_selector<_Tp>::type; };
2416
2417 template<typename _Tp>
2418 struct decay<_Tp&&>
2419 { using type = typename __decay_selector<_Tp>::type; };
2420#endif
2421
2422 /// @cond undocumented
2423
2424 // Helper which adds a reference to a type when given a reference_wrapper
2425 template<typename _Tp>
2426 struct __strip_reference_wrapper
2427 {
2428 using __type = _Tp;
2429 };
2430
2431 template<typename _Tp>
2432 struct __strip_reference_wrapper<reference_wrapper<_Tp> >
2433 {
2434 using __type = _Tp&;
2435 };
2436
2437 // __decay_t (std::decay_t for C++11).
2438 template<typename _Tp>
2439 using __decay_t = typename decay<_Tp>::type;
2440
2441 template<typename _Tp>
2442 using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>;
2443 /// @endcond
2444
2445 /// @cond undocumented
2446
2447 // Helper for SFINAE constraints
2448 template<typename... _Cond>
2449 using _Require = __enable_if_t<__and_<_Cond...>::value>;
2450
2451 // __remove_cvref_t (std::remove_cvref_t for C++11).
2452 template<typename _Tp>
2453 using __remove_cvref_t
2454 = typename remove_cv<typename remove_reference<_Tp>::type>::type;
2455 /// @endcond
2456
2457 // Primary template.
2458 /// Define a member typedef @c type to one of two argument types.
2459 template<bool _Cond, typename _Iftrue, typename _Iffalse>
2460 struct conditional
2461 { using type = _Iftrue; };
2462
2463 // Partial specialization for false.
2464 template<typename _Iftrue, typename _Iffalse>
2465 struct conditional<false, _Iftrue, _Iffalse>
2466 { using type = _Iffalse; };
2467
2468 /// common_type
2469 template<typename... _Tp>
2470 struct common_type;
2471
2472 // Sfinae-friendly common_type implementation:
2473
2474 /// @cond undocumented
2475
2476 // For several sfinae-friendly trait implementations we transport both the
2477 // result information (as the member type) and the failure information (no
2478 // member type). This is very similar to std::enable_if, but we cannot use
2479 // that, because we need to derive from them as an implementation detail.
2480
2481 template<typename _Tp>
2482 struct __success_type
2483 { using type = _Tp; };
2484
2485 struct __failure_type
2486 { };
2487
2488 struct __do_common_type_impl
2489 {
2490 template<typename _Tp, typename _Up>
2491 using __cond_t
2492 = decltype(true ? std::declval<_Tp>() : std::declval<_Up>());
2493
2494 // if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
2495 // denotes a valid type, let C denote that type.
2496 template<typename _Tp, typename _Up>
2497 static __success_type<__decay_t<__cond_t<_Tp, _Up>>>
2498 _S_test(int);
2499
2500#if __cplusplus > 201703L
2501 // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type,
2502 // let C denote the type decay_t<COND-RES(CREF(D1), CREF(D2))>.
2503 template<typename _Tp, typename _Up>
2504 static __success_type<__remove_cvref_t<__cond_t<const _Tp&, const _Up&>>>
2505 _S_test_2(int);
2506#endif
2507
2508 template<typename, typename>
2509 static __failure_type
2510 _S_test_2(...);
2511
2512 template<typename _Tp, typename _Up>
2513 static decltype(_S_test_2<_Tp, _Up>(0))
2514 _S_test(...);
2515 };
2516
2517 // If sizeof...(T) is zero, there shall be no member type.
2518 template<>
2519 struct common_type<>
2520 { };
2521
2522 // If sizeof...(T) is one, the same type, if any, as common_type_t<T0, T0>.
2523 template<typename _Tp0>
2524 struct common_type<_Tp0>
2525 : public common_type<_Tp0, _Tp0>
2526 { };
2527
2528 // If sizeof...(T) is two, ...
2529 template<typename _Tp1, typename _Tp2,
2530 typename _Dp1 = __decay_t<_Tp1>, typename _Dp2 = __decay_t<_Tp2>>
2531 struct __common_type_impl
2532 {
2533 // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false,
2534 // let C denote the same type, if any, as common_type_t<D1, D2>.
2535 using type = common_type<_Dp1, _Dp2>;
2536 };
2537
2538 template<typename _Tp1, typename _Tp2>
2539 struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2>
2540 : private __do_common_type_impl
2541 {
2542 // Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
2543 // denotes a valid type, let C denote that type.
2544 using type = decltype(_S_test<_Tp1, _Tp2>(0));
2545 };
2546
2547 // If sizeof...(T) is two, ...
2548 template<typename _Tp1, typename _Tp2>
2549 struct common_type<_Tp1, _Tp2>
2550 : public __common_type_impl<_Tp1, _Tp2>::type
2551 { };
2552
2553 template<typename...>
2554 struct __common_type_pack
2555 { };
2556
2557 template<typename, typename, typename = void>
2558 struct __common_type_fold;
2559
2560 // If sizeof...(T) is greater than two, ...
2561 template<typename _Tp1, typename _Tp2, typename... _Rp>
2562 struct common_type<_Tp1, _Tp2, _Rp...>
2563 : public __common_type_fold<common_type<_Tp1, _Tp2>,
2564 __common_type_pack<_Rp...>>
2565 { };
2566
2567 // Let C denote the same type, if any, as common_type_t<T1, T2>.
2568 // If there is such a type C, type shall denote the same type, if any,
2569 // as common_type_t<C, R...>.
2570 template<typename _CTp, typename... _Rp>
2571 struct __common_type_fold<_CTp, __common_type_pack<_Rp...>,
2572 __void_t<typename _CTp::type>>
2573 : public common_type<typename _CTp::type, _Rp...>
2574 { };
2575
2576 // Otherwise, there shall be no member type.
2577 template<typename _CTp, typename _Rp>
2578 struct __common_type_fold<_CTp, _Rp, void>
2579 { };
2580
2581 template<typename _Tp, bool = __is_enum(_Tp)>
2582 struct __underlying_type_impl
2583 {
2584 using type = __underlying_type(_Tp);
2585 };
2586
2587 template<typename _Tp>
2588 struct __underlying_type_impl<_Tp, false>
2589 { };
2590 /// @endcond
2591
2592 /// The underlying type of an enum.
2593 template<typename _Tp>
2594 struct underlying_type
2595 : public __underlying_type_impl<_Tp>
2596 { };
2597
2598 /// @cond undocumented
2599 template<typename _Tp>
2600 struct __declval_protector
2601 {
2602 static const bool __stop = false;
2603 };
2604 /// @endcond
2605
2606 /** Utility to simplify expressions used in unevaluated operands
2607 * @since C++11
2608 * @ingroup utilities
2609 */
2610 template<typename _Tp>
2611 auto declval() noexcept -> decltype(__declval<_Tp>(0))
2612 {
2613 static_assert(__declval_protector<_Tp>::__stop,
2614 "declval() must not be used!");
2615 return __declval<_Tp>(0);
2616 }
2617
2618 /// result_of
2619 template<typename _Signature>
2620 struct result_of;
2621
2622 // Sfinae-friendly result_of implementation:
2623
2624 /// @cond undocumented
2625 struct __invoke_memfun_ref { };
2626 struct __invoke_memfun_deref { };
2627 struct __invoke_memobj_ref { };
2628 struct __invoke_memobj_deref { };
2629 struct __invoke_other { };
2630
2631 // Associate a tag type with a specialization of __success_type.
2632 template<typename _Tp, typename _Tag>
2633 struct __result_of_success : __success_type<_Tp>
2634 { using __invoke_type = _Tag; };
2635
2636 // [func.require] paragraph 1 bullet 1:
2637 struct __result_of_memfun_ref_impl
2638 {
2639 template<typename _Fp, typename _Tp1, typename... _Args>
2640 static __result_of_success<decltype(
2641 (std::declval<_Tp1>().*std::declval<_Fp>())(std::declval<_Args>()...)
2642 ), __invoke_memfun_ref> _S_test(int);
2643
2644 template<typename...>
2645 static __failure_type _S_test(...);
2646 };
2647
2648 template<typename _MemPtr, typename _Arg, typename... _Args>
2649 struct __result_of_memfun_ref
2650 : private __result_of_memfun_ref_impl
2651 {
2652 using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0));
2653 };
2654
2655 // [func.require] paragraph 1 bullet 2:
2656 struct __result_of_memfun_deref_impl
2657 {
2658 template<typename _Fp, typename _Tp1, typename... _Args>
2659 static __result_of_success<decltype(
2660 ((*std::declval<_Tp1>()).*std::declval<_Fp>())(std::declval<_Args>()...)
2661 ), __invoke_memfun_deref> _S_test(int);
2662
2663 template<typename...>
2664 static __failure_type _S_test(...);
2665 };
2666
2667 template<typename _MemPtr, typename _Arg, typename... _Args>
2668 struct __result_of_memfun_deref
2669 : private __result_of_memfun_deref_impl
2670 {
2671 using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0));
2672 };
2673
2674 // [func.require] paragraph 1 bullet 3:
2675 struct __result_of_memobj_ref_impl
2676 {
2677 template<typename _Fp, typename _Tp1>
2678 static __result_of_success<decltype(
2679 std::declval<_Tp1>().*std::declval<_Fp>()
2680 ), __invoke_memobj_ref> _S_test(int);
2681
2682 template<typename, typename>
2683 static __failure_type _S_test(...);
2684 };
2685
2686 template<typename _MemPtr, typename _Arg>
2687 struct __result_of_memobj_ref
2688 : private __result_of_memobj_ref_impl
2689 {
2690 using type = decltype(_S_test<_MemPtr, _Arg>(0));
2691 };
2692
2693 // [func.require] paragraph 1 bullet 4:
2694 struct __result_of_memobj_deref_impl
2695 {
2696 template<typename _Fp, typename _Tp1>
2697 static __result_of_success<decltype(
2698 (*std::declval<_Tp1>()).*std::declval<_Fp>()
2699 ), __invoke_memobj_deref> _S_test(int);
2700
2701 template<typename, typename>
2702 static __failure_type _S_test(...);
2703 };
2704
2705 template<typename _MemPtr, typename _Arg>
2706 struct __result_of_memobj_deref
2707 : private __result_of_memobj_deref_impl
2708 {
2709 using type = decltype(_S_test<_MemPtr, _Arg>(0));
2710 };
2711
2712 template<typename _MemPtr, typename _Arg>
2713 struct __result_of_memobj;
2714
2715 template<typename _Res, typename _Class, typename _Arg>
2716 struct __result_of_memobj<_Res _Class::*, _Arg>
2717 {
2718 using _Argval = __remove_cvref_t<_Arg>;
2719 using _MemPtr = _Res _Class::*;
2720 using type = typename __conditional_t<__or_<is_same<_Argval, _Class>,
2721 is_base_of<_Class, _Argval>>::value,
2722 __result_of_memobj_ref<_MemPtr, _Arg>,
2723 __result_of_memobj_deref<_MemPtr, _Arg>
2724 >::type;
2725 };
2726
2727 template<typename _MemPtr, typename _Arg, typename... _Args>
2728 struct __result_of_memfun;
2729
2730 template<typename _Res, typename _Class, typename _Arg, typename... _Args>
2731 struct __result_of_memfun<_Res _Class::*, _Arg, _Args...>
2732 {
2733 using _Argval = typename remove_reference<_Arg>::type;
2734 using _MemPtr = _Res _Class::*;
2735 using type = typename __conditional_t<is_base_of<_Class, _Argval>::value,
2736 __result_of_memfun_ref<_MemPtr, _Arg, _Args...>,
2737 __result_of_memfun_deref<_MemPtr, _Arg, _Args...>
2738 >::type;
2739 };
2740
2741 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2742 // 2219. INVOKE-ing a pointer to member with a reference_wrapper
2743 // as the object expression
2744
2745 // Used by result_of, invoke etc. to unwrap a reference_wrapper.
2746 template<typename _Tp, typename _Up = __remove_cvref_t<_Tp>>
2747 struct __inv_unwrap
2748 {
2749 using type = _Tp;
2750 };
2751
2752 template<typename _Tp, typename _Up>
2753 struct __inv_unwrap<_Tp, reference_wrapper<_Up>>
2754 {
2755 using type = _Up&;
2756 };
2757
2758 template<bool, bool, typename _Functor, typename... _ArgTypes>
2759 struct __result_of_impl
2760 {
2761 using type = __failure_type;
2762 };
2763
2764 template<typename _MemPtr, typename _Arg>
2765 struct __result_of_impl<true, false, _MemPtr, _Arg>
2766 : public __result_of_memobj<__decay_t<_MemPtr>,
2767 typename __inv_unwrap<_Arg>::type>
2768 { };
2769
2770 template<typename _MemPtr, typename _Arg, typename... _Args>
2771 struct __result_of_impl<false, true, _MemPtr, _Arg, _Args...>
2772 : public __result_of_memfun<__decay_t<_MemPtr>,
2773 typename __inv_unwrap<_Arg>::type, _Args...>
2774 { };
2775
2776 // [func.require] paragraph 1 bullet 5:
2777 struct __result_of_other_impl
2778 {
2779 template<typename _Fn, typename... _Args>
2780 static __result_of_success<decltype(
2781 std::declval<_Fn>()(std::declval<_Args>()...)
2782 ), __invoke_other> _S_test(int);
2783
2784 template<typename...>
2785 static __failure_type _S_test(...);
2786 };
2787
2788 template<typename _Functor, typename... _ArgTypes>
2789 struct __result_of_impl<false, false, _Functor, _ArgTypes...>
2790 : private __result_of_other_impl
2791 {
2792 using type = decltype(_S_test<_Functor, _ArgTypes...>(0));
2793 };
2794
2795 // __invoke_result (std::invoke_result for C++11)
2796 template<typename _Functor, typename... _ArgTypes>
2797 struct __invoke_result
2798 : public __result_of_impl<
2799 is_member_object_pointer<
2800 typename remove_reference<_Functor>::type
2801 >::value,
2802 is_member_function_pointer<
2803 typename remove_reference<_Functor>::type
2804 >::value,
2805 _Functor, _ArgTypes...
2806 >::type
2807 { };
2808
2809 // __invoke_result_t (std::invoke_result_t for C++11)
2810 template<typename _Fn, typename... _Args>
2811 using __invoke_result_t = typename __invoke_result<_Fn, _Args...>::type;
2812 /// @endcond
2813
2814 template<typename _Functor, typename... _ArgTypes>
2815 struct result_of<_Functor(_ArgTypes...)>
2816 : public __invoke_result<_Functor, _ArgTypes...>
2817 { } _GLIBCXX17_DEPRECATED_SUGGEST("std::invoke_result");
2818
2819#if __cplusplus >= 201402L
2820#pragma GCC diagnostic push
2821#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2822 /// Alias template for aligned_storage
2823 template<size_t _Len,
2824 size_t _Align = __aligned_storage_default_alignment(_Len)>
2825 using aligned_storage_t _GLIBCXX23_DEPRECATED = typename aligned_storage<_Len, _Align>::type;
2826
2827 template <size_t _Len, typename... _Types>
2828 using aligned_union_t _GLIBCXX23_DEPRECATED = typename aligned_union<_Len, _Types...>::type;
2829#pragma GCC diagnostic pop
2830
2831 /// Alias template for decay
2832 template<typename _Tp>
2833 using decay_t = typename decay<_Tp>::type;
2834
2835 /// Alias template for enable_if
2836 template<bool _Cond, typename _Tp = void>
2837 using enable_if_t = typename enable_if<_Cond, _Tp>::type;
2838
2839 /// Alias template for conditional
2840 template<bool _Cond, typename _Iftrue, typename _Iffalse>
2841 using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type;
2842
2843 /// Alias template for common_type
2844 template<typename... _Tp>
2845 using common_type_t = typename common_type<_Tp...>::type;
2846
2847 /// Alias template for underlying_type
2848 template<typename _Tp>
2849 using underlying_type_t = typename underlying_type<_Tp>::type;
2850
2851 /// Alias template for result_of
2852 template<typename _Tp>
2853 using result_of_t = typename result_of<_Tp>::type;
2854#endif // C++14
2855
2856#ifdef __cpp_lib_void_t // C++ >= 17 || GNU++ >= 11
2857 /// A metafunction that always yields void, used for detecting valid types.
2858 template<typename...> using void_t = void;
2859#endif
2860
2861 /// @cond undocumented
2862
2863 // Detection idiom.
2864 // Detect whether _Op<_Args...> is a valid type, use default _Def if not.
2865
2866#if __cpp_concepts
2867 // Implementation of the detection idiom (negative case).
2868 template<typename _Def, template<typename...> class _Op, typename... _Args>
2869 struct __detected_or
2870 {
2871 using type = _Def;
2872 using __is_detected = false_type;
2873 };
2874
2875 // Implementation of the detection idiom (positive case).
2876 template<typename _Def, template<typename...> class _Op, typename... _Args>
2877 requires requires { typename _Op<_Args...>; }
2878 struct __detected_or<_Def, _Op, _Args...>
2879 {
2880 using type = _Op<_Args...>;
2881 using __is_detected = true_type;
2882 };
2883#else
2884 /// Implementation of the detection idiom (negative case).
2885 template<typename _Default, typename _AlwaysVoid,
2886 template<typename...> class _Op, typename... _Args>
2887 struct __detector
2888 {
2889 using type = _Default;
2890 using __is_detected = false_type;
2891 };
2892
2893 /// Implementation of the detection idiom (positive case).
2894 template<typename _Default, template<typename...> class _Op,
2895 typename... _Args>
2896 struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...>
2897 {
2898 using type = _Op<_Args...>;
2899 using __is_detected = true_type;
2900 };
2901
2902 template<typename _Default, template<typename...> class _Op,
2903 typename... _Args>
2904 using __detected_or = __detector<_Default, void, _Op, _Args...>;
2905#endif // __cpp_concepts
2906
2907 // _Op<_Args...> if that is a valid type, otherwise _Default.
2908 template<typename _Default, template<typename...> class _Op,
2909 typename... _Args>
2910 using __detected_or_t
2911 = typename __detected_or<_Default, _Op, _Args...>::type;
2912
2913 /**
2914 * Use SFINAE to determine if the type _Tp has a publicly-accessible
2915 * member type _NTYPE.
2916 */
2917#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \
2918 template<typename _Tp, typename = __void_t<>> \
2919 struct __has_##_NTYPE \
2920 : false_type \
2921 { }; \
2922 template<typename _Tp> \
2923 struct __has_##_NTYPE<_Tp, __void_t<typename _Tp::_NTYPE>> \
2924 : true_type \
2925 { };
2926
2927 template <typename _Tp>
2928 struct __is_swappable;
2929
2930 template <typename _Tp>
2931 struct __is_nothrow_swappable;
2932
2933 template<typename>
2934 struct __is_tuple_like_impl : false_type
2935 { };
2936
2937 // Internal type trait that allows us to sfinae-protect tuple_cat.
2938 template<typename _Tp>
2939 struct __is_tuple_like
2940 : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type
2941 { };
2942 /// @endcond
2943
2944 template<typename _Tp>
2945 _GLIBCXX20_CONSTEXPR
2946 inline
2947 _Require<__not_<__is_tuple_like<_Tp>>,
2948 is_move_constructible<_Tp>,
2949 is_move_assignable<_Tp>>
2950 swap(_Tp&, _Tp&)
2951 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
2952 is_nothrow_move_assignable<_Tp>>::value);
2953
2954 template<typename _Tp, size_t _Nm>
2955 _GLIBCXX20_CONSTEXPR
2956 inline
2957 __enable_if_t<__is_swappable<_Tp>::value>
2958 swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
2959 noexcept(__is_nothrow_swappable<_Tp>::value);
2960
2961 /// @cond undocumented
2962 namespace __swappable_details {
2963 using std::swap;
2964
2965 struct __do_is_swappable_impl
2966 {
2967 template<typename _Tp, typename
2968 = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))>
2969 static true_type __test(int);
2970
2971 template<typename>
2972 static false_type __test(...);
2973 };
2974
2975 struct __do_is_nothrow_swappable_impl
2976 {
2977 template<typename _Tp>
2978 static __bool_constant<
2979 noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))
2980 > __test(int);
2981
2982 template<typename>
2983 static false_type __test(...);
2984 };
2985
2986 } // namespace __swappable_details
2987
2988 template<typename _Tp>
2989 struct __is_swappable_impl
2990 : public __swappable_details::__do_is_swappable_impl
2991 {
2992 using type = decltype(__test<_Tp>(0));
2993 };
2994
2995 template<typename _Tp>
2996 struct __is_nothrow_swappable_impl
2997 : public __swappable_details::__do_is_nothrow_swappable_impl
2998 {
2999 using type = decltype(__test<_Tp>(0));
3000 };
3001
3002 template<typename _Tp>
3003 struct __is_swappable
3004 : public __is_swappable_impl<_Tp>::type
3005 { };
3006
3007 template<typename _Tp>
3008 struct __is_nothrow_swappable
3009 : public __is_nothrow_swappable_impl<_Tp>::type
3010 { };
3011 /// @endcond
3012
3013#ifdef __cpp_lib_is_swappable // C++ >= 17 || GNU++ >= 11
3014 /// Metafunctions used for detecting swappable types: p0185r1
3015
3016 /// is_swappable
3017 template<typename _Tp>
3018 struct is_swappable
3019 : public __is_swappable_impl<_Tp>::type
3020 {
3021 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
3022 "template argument must be a complete class or an unbounded array");
3023 };
3024
3025 /// is_nothrow_swappable
3026 template<typename _Tp>
3027 struct is_nothrow_swappable
3028 : public __is_nothrow_swappable_impl<_Tp>::type
3029 {
3030 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
3031 "template argument must be a complete class or an unbounded array");
3032 };
3033
3034#if __cplusplus >= 201402L
3035 /// is_swappable_v
3036 template<typename _Tp>
3037 _GLIBCXX17_INLINE constexpr bool is_swappable_v =
3038 is_swappable<_Tp>::value;
3039
3040 /// is_nothrow_swappable_v
3041 template<typename _Tp>
3042 _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v =
3043 is_nothrow_swappable<_Tp>::value;
3044#endif // __cplusplus >= 201402L
3045
3046 /// @cond undocumented
3047 namespace __swappable_with_details {
3048 using std::swap;
3049
3050 struct __do_is_swappable_with_impl
3051 {
3052 template<typename _Tp, typename _Up, typename
3053 = decltype(swap(std::declval<_Tp>(), std::declval<_Up>())),
3054 typename
3055 = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))>
3056 static true_type __test(int);
3057
3058 template<typename, typename>
3059 static false_type __test(...);
3060 };
3061
3062 struct __do_is_nothrow_swappable_with_impl
3063 {
3064 template<typename _Tp, typename _Up>
3065 static __bool_constant<
3066 noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()))
3067 &&
3068 noexcept(swap(std::declval<_Up>(), std::declval<_Tp>()))
3069 > __test(int);
3070
3071 template<typename, typename>
3072 static false_type __test(...);
3073 };
3074
3075 } // namespace __swappable_with_details
3076
3077 template<typename _Tp, typename _Up>
3078 struct __is_swappable_with_impl
3079 : public __swappable_with_details::__do_is_swappable_with_impl
3080 {
3081 using type = decltype(__test<_Tp, _Up>(0));
3082 };
3083
3084 // Optimization for the homogenous lvalue case, not required:
3085 template<typename _Tp>
3086 struct __is_swappable_with_impl<_Tp&, _Tp&>
3087 : public __swappable_details::__do_is_swappable_impl
3088 {
3089 using type = decltype(__test<_Tp&>(0));
3090 };
3091
3092 template<typename _Tp, typename _Up>
3093 struct __is_nothrow_swappable_with_impl
3094 : public __swappable_with_details::__do_is_nothrow_swappable_with_impl
3095 {
3096 using type = decltype(__test<_Tp, _Up>(0));
3097 };
3098
3099 // Optimization for the homogenous lvalue case, not required:
3100 template<typename _Tp>
3101 struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&>
3102 : public __swappable_details::__do_is_nothrow_swappable_impl
3103 {
3104 using type = decltype(__test<_Tp&>(0));
3105 };
3106 /// @endcond
3107
3108 /// is_swappable_with
3109 template<typename _Tp, typename _Up>
3110 struct is_swappable_with
3111 : public __is_swappable_with_impl<_Tp, _Up>::type
3112 {
3113 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
3114 "first template argument must be a complete class or an unbounded array");
3115 static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
3116 "second template argument must be a complete class or an unbounded array");
3117 };
3118
3119 /// is_nothrow_swappable_with
3120 template<typename _Tp, typename _Up>
3121 struct is_nothrow_swappable_with
3122 : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type
3123 {
3124 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
3125 "first template argument must be a complete class or an unbounded array");
3126 static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
3127 "second template argument must be a complete class or an unbounded array");
3128 };
3129
3130#if __cplusplus >= 201402L
3131 /// is_swappable_with_v
3132 template<typename _Tp, typename _Up>
3133 _GLIBCXX17_INLINE constexpr bool is_swappable_with_v =
3134 is_swappable_with<_Tp, _Up>::value;
3135
3136 /// is_nothrow_swappable_with_v
3137 template<typename _Tp, typename _Up>
3138 _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v =
3139 is_nothrow_swappable_with<_Tp, _Up>::value;
3140#endif // __cplusplus >= 201402L
3141
3142#endif // __cpp_lib_is_swappable
3143
3144 /// @cond undocumented
3145
3146 // __is_invocable (std::is_invocable for C++11)
3147
3148 // The primary template is used for invalid INVOKE expressions.
3149 template<typename _Result, typename _Ret,
3150 bool = is_void<_Ret>::value, typename = void>
3151 struct __is_invocable_impl
3152 : false_type
3153 {
3154 using __nothrow_conv = false_type; // For is_nothrow_invocable_r
3155 };
3156
3157 // Used for valid INVOKE and INVOKE<void> expressions.
3158 template<typename _Result, typename _Ret>
3159 struct __is_invocable_impl<_Result, _Ret,
3160 /* is_void<_Ret> = */ true,
3161 __void_t<typename _Result::type>>
3162 : true_type
3163 {
3164 using __nothrow_conv = true_type; // For is_nothrow_invocable_r
3165 };
3166
3167#pragma GCC diagnostic push
3168#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
3169 // Used for INVOKE<R> expressions to check the implicit conversion to R.
3170 template<typename _Result, typename _Ret>
3171 struct __is_invocable_impl<_Result, _Ret,
3172 /* is_void<_Ret> = */ false,
3173 __void_t<typename _Result::type>>
3174 {
3175 private:
3176 // The type of the INVOKE expression.
3177 using _Res_t = typename _Result::type;
3178
3179 // Unlike declval, this doesn't add_rvalue_reference, so it respects
3180 // guaranteed copy elision.
3181 static _Res_t _S_get() noexcept;
3182
3183 // Used to check if _Res_t can implicitly convert to _Tp.
3184 template<typename _Tp>
3185 static void _S_conv(__type_identity_t<_Tp>) noexcept;
3186
3187 // This overload is viable if INVOKE(f, args...) can convert to _Tp.
3188 template<typename _Tp,
3189 bool _Nothrow = noexcept(_S_conv<_Tp>(_S_get())),
3190 typename = decltype(_S_conv<_Tp>(_S_get())),
3191#if __has_builtin(__reference_converts_from_temporary)
3192 bool _Dangle = __reference_converts_from_temporary(_Tp, _Res_t)
3193#else
3194 bool _Dangle = false
3195#endif
3196 >
3197 static __bool_constant<_Nothrow && !_Dangle>
3198 _S_test(int);
3199
3200 template<typename _Tp, bool = false>
3201 static false_type
3202 _S_test(...);
3203
3204 public:
3205 // For is_invocable_r
3206 using type = decltype(_S_test<_Ret, /* Nothrow = */ true>(1));
3207
3208 // For is_nothrow_invocable_r
3209 using __nothrow_conv = decltype(_S_test<_Ret>(1));
3210 };
3211#pragma GCC diagnostic pop
3212
3213 template<typename _Fn, typename... _ArgTypes>
3214 struct __is_invocable
3215 : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
3216 { };
3217
3218 template<typename _Fn, typename _Tp, typename... _Args>
3219 constexpr bool __call_is_nt(__invoke_memfun_ref)
3220 {
3221 using _Up = typename __inv_unwrap<_Tp>::type;
3222 return noexcept((std::declval<_Up>().*std::declval<_Fn>())(
3223 std::declval<_Args>()...));
3224 }
3225
3226 template<typename _Fn, typename _Tp, typename... _Args>
3227 constexpr bool __call_is_nt(__invoke_memfun_deref)
3228 {
3229 return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())(
3230 std::declval<_Args>()...));
3231 }
3232
3233 template<typename _Fn, typename _Tp>
3234 constexpr bool __call_is_nt(__invoke_memobj_ref)
3235 {
3236 using _Up = typename __inv_unwrap<_Tp>::type;
3237 return noexcept(std::declval<_Up>().*std::declval<_Fn>());
3238 }
3239
3240 template<typename _Fn, typename _Tp>
3241 constexpr bool __call_is_nt(__invoke_memobj_deref)
3242 {
3243 return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>());
3244 }
3245
3246 template<typename _Fn, typename... _Args>
3247 constexpr bool __call_is_nt(__invoke_other)
3248 {
3249 return noexcept(std::declval<_Fn>()(std::declval<_Args>()...));
3250 }
3251
3252 template<typename _Result, typename _Fn, typename... _Args>
3253 struct __call_is_nothrow
3254 : __bool_constant<
3255 std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{})
3256 >
3257 { };
3258
3259 template<typename _Fn, typename... _Args>
3260 using __call_is_nothrow_
3261 = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>;
3262
3263 // __is_nothrow_invocable (std::is_nothrow_invocable for C++11)
3264 template<typename _Fn, typename... _Args>
3265 struct __is_nothrow_invocable
3266 : __and_<__is_invocable<_Fn, _Args...>,
3267 __call_is_nothrow_<_Fn, _Args...>>::type
3268 { };
3269
3270#pragma GCC diagnostic push
3271#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
3272 struct __nonesuchbase {};
3273 struct __nonesuch : private __nonesuchbase {
3274 ~__nonesuch() = delete;
3275 __nonesuch(__nonesuch const&) = delete;
3276 void operator=(__nonesuch const&) = delete;
3277 };
3278#pragma GCC diagnostic pop
3279 /// @endcond
3280
3281#ifdef __cpp_lib_is_invocable // C++ >= 17
3282 /// std::invoke_result
3283 template<typename _Functor, typename... _ArgTypes>
3284 struct invoke_result
3285 : public __invoke_result<_Functor, _ArgTypes...>
3286 {
3287 static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}),
3288 "_Functor must be a complete class or an unbounded array");
3289 static_assert((std::__is_complete_or_unbounded(
3290 __type_identity<_ArgTypes>{}) && ...),
3291 "each argument type must be a complete class or an unbounded array");
3292 };
3293
3294 /// std::invoke_result_t
3295 template<typename _Fn, typename... _Args>
3296 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
3297
3298 /// std::is_invocable
3299 template<typename _Fn, typename... _ArgTypes>
3300 struct is_invocable
3301#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable)
3302 : public __bool_constant<__is_invocable(_Fn, _ArgTypes...)>
3303#else
3304 : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
3305#endif
3306 {
3307 static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
3308 "_Fn must be a complete class or an unbounded array");
3309 static_assert((std::__is_complete_or_unbounded(
3310 __type_identity<_ArgTypes>{}) && ...),
3311 "each argument type must be a complete class or an unbounded array");
3312 };
3313
3314 /// std::is_invocable_r
3315 template<typename _Ret, typename _Fn, typename... _ArgTypes>
3316 struct is_invocable_r
3317 : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type
3318 {
3319 static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
3320 "_Fn must be a complete class or an unbounded array");
3321 static_assert((std::__is_complete_or_unbounded(
3322 __type_identity<_ArgTypes>{}) && ...),
3323 "each argument type must be a complete class or an unbounded array");
3324 static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
3325 "_Ret must be a complete class or an unbounded array");
3326 };
3327
3328 /// std::is_nothrow_invocable
3329 template<typename _Fn, typename... _ArgTypes>
3330 struct is_nothrow_invocable
3331#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable)
3332 : public __bool_constant<__is_nothrow_invocable(_Fn, _ArgTypes...)>
3333#else
3334 : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>,
3335 __call_is_nothrow_<_Fn, _ArgTypes...>>::type
3336#endif
3337 {
3338 static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
3339 "_Fn must be a complete class or an unbounded array");
3340 static_assert((std::__is_complete_or_unbounded(
3341 __type_identity<_ArgTypes>{}) && ...),
3342 "each argument type must be a complete class or an unbounded array");
3343 };
3344
3345 /// @cond undocumented
3346 // This checks that the INVOKE<R> expression is well-formed and that the
3347 // conversion to R does not throw. It does *not* check whether the INVOKE
3348 // expression itself can throw. That is done by __call_is_nothrow_ instead.
3349 template<typename _Result, typename _Ret>
3350 using __is_nt_invocable_impl
3351 = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv;
3352 /// @endcond
3353
3354 /// std::is_nothrow_invocable_r
3355 template<typename _Ret, typename _Fn, typename... _ArgTypes>
3356 struct is_nothrow_invocable_r
3357 : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>,
3358 __call_is_nothrow_<_Fn, _ArgTypes...>>::type
3359 {
3360 static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
3361 "_Fn must be a complete class or an unbounded array");
3362 static_assert((std::__is_complete_or_unbounded(
3363 __type_identity<_ArgTypes>{}) && ...),
3364 "each argument type must be a complete class or an unbounded array");
3365 static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
3366 "_Ret must be a complete class or an unbounded array");
3367 };
3368#endif // __cpp_lib_is_invocable
3369
3370#if __cpp_lib_type_trait_variable_templates // C++ >= 17
3371 /**
3372 * @defgroup variable_templates Variable templates for type traits
3373 * @ingroup metaprogramming
3374 *
3375 * Each variable `is_xxx_v<T>` is a boolean constant with the same value
3376 * as the `value` member of the corresponding type trait `is_xxx<T>`.
3377 *
3378 * @since C++17 unless noted otherwise.
3379 */
3380
3381 /**
3382 * @{
3383 * @ingroup variable_templates
3384 */
3385template <typename _Tp>
3386 inline constexpr bool is_void_v = is_void<_Tp>::value;
3387template <typename _Tp>
3388 inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
3389template <typename _Tp>
3390 inline constexpr bool is_integral_v = is_integral<_Tp>::value;
3391template <typename _Tp>
3392 inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
3393
3394#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
3395template <typename _Tp>
3396 inline constexpr bool is_array_v = __is_array(_Tp);
3397#else
3398template <typename _Tp>
3399 inline constexpr bool is_array_v = false;
3400template <typename _Tp>
3401 inline constexpr bool is_array_v<_Tp[]> = true;
3402template <typename _Tp, size_t _Num>
3403 inline constexpr bool is_array_v<_Tp[_Num]> = true;
3404#endif
3405
3406#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer)
3407template <typename _Tp>
3408 inline constexpr bool is_pointer_v = __is_pointer(_Tp);
3409#else
3410template <typename _Tp>
3411 inline constexpr bool is_pointer_v = false;
3412template <typename _Tp>
3413 inline constexpr bool is_pointer_v<_Tp*> = true;
3414template <typename _Tp>
3415 inline constexpr bool is_pointer_v<_Tp* const> = true;
3416template <typename _Tp>
3417 inline constexpr bool is_pointer_v<_Tp* volatile> = true;
3418template <typename _Tp>
3419 inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
3420#endif
3421
3422template <typename _Tp>
3423 inline constexpr bool is_lvalue_reference_v = false;
3424template <typename _Tp>
3425 inline constexpr bool is_lvalue_reference_v<_Tp&> = true;
3426template <typename _Tp>
3427 inline constexpr bool is_rvalue_reference_v = false;
3428template <typename _Tp>
3429 inline constexpr bool is_rvalue_reference_v<_Tp&&> = true;
3430
3431#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
3432template <typename _Tp>
3433 inline constexpr bool is_member_object_pointer_v =
3434 __is_member_object_pointer(_Tp);
3435#else
3436template <typename _Tp>
3437 inline constexpr bool is_member_object_pointer_v =
3438 is_member_object_pointer<_Tp>::value;
3439#endif
3440
3441#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
3442template <typename _Tp>
3443 inline constexpr bool is_member_function_pointer_v =
3444 __is_member_function_pointer(_Tp);
3445#else
3446template <typename _Tp>
3447 inline constexpr bool is_member_function_pointer_v =
3448 is_member_function_pointer<_Tp>::value;
3449#endif
3450
3451template <typename _Tp>
3452 inline constexpr bool is_enum_v = __is_enum(_Tp);
3453template <typename _Tp>
3454 inline constexpr bool is_union_v = __is_union(_Tp);
3455template <typename _Tp>
3456 inline constexpr bool is_class_v = __is_class(_Tp);
3457// is_function_v is defined below, after is_const_v.
3458
3459#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
3460template <typename _Tp>
3461 inline constexpr bool is_reference_v = __is_reference(_Tp);
3462#else
3463template <typename _Tp>
3464 inline constexpr bool is_reference_v = false;
3465template <typename _Tp>
3466 inline constexpr bool is_reference_v<_Tp&> = true;
3467template <typename _Tp>
3468 inline constexpr bool is_reference_v<_Tp&&> = true;
3469#endif
3470
3471template <typename _Tp>
3472 inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
3473template <typename _Tp>
3474 inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
3475
3476#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object)
3477template <typename _Tp>
3478 inline constexpr bool is_object_v = __is_object(_Tp);
3479#else
3480template <typename _Tp>
3481 inline constexpr bool is_object_v = is_object<_Tp>::value;
3482#endif
3483
3484template <typename _Tp>
3485 inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
3486template <typename _Tp>
3487 inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>;
3488
3489#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
3490template <typename _Tp>
3491 inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp);
3492#else
3493template <typename _Tp>
3494 inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
3495#endif
3496
3497#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const)
3498template <typename _Tp>
3499 inline constexpr bool is_const_v = __is_const(_Tp);
3500#else
3501template <typename _Tp>
3502 inline constexpr bool is_const_v = false;
3503template <typename _Tp>
3504 inline constexpr bool is_const_v<const _Tp> = true;
3505#endif
3506
3507#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
3508template <typename _Tp>
3509 inline constexpr bool is_function_v = __is_function(_Tp);
3510#else
3511template <typename _Tp>
3512 inline constexpr bool is_function_v = !is_const_v<const _Tp>;
3513template <typename _Tp>
3514 inline constexpr bool is_function_v<_Tp&> = false;
3515template <typename _Tp>
3516 inline constexpr bool is_function_v<_Tp&&> = false;
3517#endif
3518
3519#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile)
3520template <typename _Tp>
3521 inline constexpr bool is_volatile_v = __is_volatile(_Tp);
3522#else
3523template <typename _Tp>
3524 inline constexpr bool is_volatile_v = false;
3525template <typename _Tp>
3526 inline constexpr bool is_volatile_v<volatile _Tp> = true;
3527#endif
3528
3529template <typename _Tp>
3530 _GLIBCXX26_DEPRECATED_SUGGEST("is_trivially_default_constructible_v && is_trivially_copyable_v")
3531 inline constexpr bool is_trivial_v = __is_trivial(_Tp);
3532template <typename _Tp>
3533 inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp);
3534template <typename _Tp>
3535 inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp);
3536template <typename _Tp>
3537 _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout_v && is_trivial_v")
3538 inline constexpr bool is_pod_v = __is_pod(_Tp);
3539template <typename _Tp>
3540 _GLIBCXX17_DEPRECATED
3541 inline constexpr bool is_literal_type_v = __is_literal_type(_Tp);
3542template <typename _Tp>
3543 inline constexpr bool is_empty_v = __is_empty(_Tp);
3544template <typename _Tp>
3545 inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp);
3546template <typename _Tp>
3547 inline constexpr bool is_abstract_v = __is_abstract(_Tp);
3548template <typename _Tp>
3549 inline constexpr bool is_final_v = __is_final(_Tp);
3550
3551template <typename _Tp>
3552 inline constexpr bool is_signed_v = is_signed<_Tp>::value;
3553template <typename _Tp>
3554 inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
3555
3556template <typename _Tp, typename... _Args>
3557 inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
3558template <typename _Tp>
3559 inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
3560template <typename _Tp>
3561 inline constexpr bool is_copy_constructible_v
3562 = __is_constructible(_Tp, __add_lval_ref_t<const _Tp>);
3563template <typename _Tp>
3564 inline constexpr bool is_move_constructible_v
3565 = __is_constructible(_Tp, __add_rval_ref_t<_Tp>);
3566
3567template <typename _Tp, typename _Up>
3568 inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up);
3569template <typename _Tp>
3570 inline constexpr bool is_copy_assignable_v
3571 = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>);
3572template <typename _Tp>
3573 inline constexpr bool is_move_assignable_v
3574 = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
3575
3576template <typename _Tp>
3577 inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
3578
3579template <typename _Tp, typename... _Args>
3580 inline constexpr bool is_trivially_constructible_v
3581 = __is_trivially_constructible(_Tp, _Args...);
3582template <typename _Tp>
3583 inline constexpr bool is_trivially_default_constructible_v
3584 = __is_trivially_constructible(_Tp);
3585template <typename _Tp>
3586 inline constexpr bool is_trivially_copy_constructible_v
3587 = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
3588template <typename _Tp>
3589 inline constexpr bool is_trivially_move_constructible_v
3590 = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>);
3591
3592template <typename _Tp, typename _Up>
3593 inline constexpr bool is_trivially_assignable_v
3594 = __is_trivially_assignable(_Tp, _Up);
3595template <typename _Tp>
3596 inline constexpr bool is_trivially_copy_assignable_v
3597 = __is_trivially_assignable(__add_lval_ref_t<_Tp>,
3598 __add_lval_ref_t<const _Tp>);
3599template <typename _Tp>
3600 inline constexpr bool is_trivially_move_assignable_v
3601 = __is_trivially_assignable(__add_lval_ref_t<_Tp>,
3602 __add_rval_ref_t<_Tp>);
3603
3604#if __cpp_concepts
3605template <typename _Tp>
3606 inline constexpr bool is_trivially_destructible_v = false;
3607
3608template <typename _Tp>
3609 requires (!is_reference_v<_Tp>) && requires (_Tp& __t) { __t.~_Tp(); }
3610 inline constexpr bool is_trivially_destructible_v<_Tp>
3611 = __has_trivial_destructor(_Tp);
3612template <typename _Tp>
3613 inline constexpr bool is_trivially_destructible_v<_Tp&> = true;
3614template <typename _Tp>
3615 inline constexpr bool is_trivially_destructible_v<_Tp&&> = true;
3616template <typename _Tp, size_t _Nm>
3617 inline constexpr bool is_trivially_destructible_v<_Tp[_Nm]>
3618 = is_trivially_destructible_v<_Tp>;
3619#else
3620template <typename _Tp>
3621 inline constexpr bool is_trivially_destructible_v =
3622 is_trivially_destructible<_Tp>::value;
3623#endif
3624
3625template <typename _Tp, typename... _Args>
3626 inline constexpr bool is_nothrow_constructible_v
3627 = __is_nothrow_constructible(_Tp, _Args...);
3628template <typename _Tp>
3629 inline constexpr bool is_nothrow_default_constructible_v
3630 = __is_nothrow_constructible(_Tp);
3631template <typename _Tp>
3632 inline constexpr bool is_nothrow_copy_constructible_v
3633 = __is_nothrow_constructible(_Tp, __add_lval_ref_t<const _Tp>);
3634template <typename _Tp>
3635 inline constexpr bool is_nothrow_move_constructible_v
3636 = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>);
3637
3638template <typename _Tp, typename _Up>
3639 inline constexpr bool is_nothrow_assignable_v
3640 = __is_nothrow_assignable(_Tp, _Up);
3641template <typename _Tp>
3642 inline constexpr bool is_nothrow_copy_assignable_v
3643 = __is_nothrow_assignable(__add_lval_ref_t<_Tp>,
3644 __add_lval_ref_t<const _Tp>);
3645template <typename _Tp>
3646 inline constexpr bool is_nothrow_move_assignable_v
3647 = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
3648
3649template <typename _Tp>
3650 inline constexpr bool is_nothrow_destructible_v =
3651 is_nothrow_destructible<_Tp>::value;
3652
3653template <typename _Tp>
3654 inline constexpr bool has_virtual_destructor_v
3655 = __has_virtual_destructor(_Tp);
3656
3657template <typename _Tp>
3658 inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value;
3659
3660#if _GLIBCXX_USE_BUILTIN_TRAIT(__array_rank) \
3661 && (!defined(__clang__) || __clang_major__ >= 20) // PR118559
3662template <typename _Tp>
3663 inline constexpr size_t rank_v = __array_rank(_Tp);
3664#else
3665template <typename _Tp>
3666 inline constexpr size_t rank_v = 0;
3667template <typename _Tp, size_t _Size>
3668 inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>;
3669template <typename _Tp>
3670 inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>;
3671#endif
3672
3673template <typename _Tp, unsigned _Idx = 0>
3674 inline constexpr size_t extent_v = 0;
3675template <typename _Tp, size_t _Size>
3676 inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size;
3677template <typename _Tp, unsigned _Idx, size_t _Size>
3678 inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>;
3679template <typename _Tp>
3680 inline constexpr size_t extent_v<_Tp[], 0> = 0;
3681template <typename _Tp, unsigned _Idx>
3682 inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>;
3683
3684#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same)
3685template <typename _Tp, typename _Up>
3686 inline constexpr bool is_same_v = __is_same(_Tp, _Up);
3687#else
3688template <typename _Tp, typename _Up>
3689 inline constexpr bool is_same_v = false;
3690template <typename _Tp>
3691 inline constexpr bool is_same_v<_Tp, _Tp> = true;
3692#endif
3693template <typename _Base, typename _Derived>
3694 inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived);
3695#ifdef __cpp_lib_is_virtual_base_of // C++ >= 26
3696template <typename _Base, typename _Derived>
3697 inline constexpr bool is_virtual_base_of_v = __builtin_is_virtual_base_of(_Base, _Derived);
3698#endif
3699#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible)
3700template <typename _From, typename _To>
3701 inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
3702#else
3703template <typename _From, typename _To>
3704 inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
3705#endif
3706template<typename _Fn, typename... _Args>
3707 inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
3708template<typename _Fn, typename... _Args>
3709 inline constexpr bool is_nothrow_invocable_v
3710 = is_nothrow_invocable<_Fn, _Args...>::value;
3711template<typename _Ret, typename _Fn, typename... _Args>
3712 inline constexpr bool is_invocable_r_v
3713 = is_invocable_r<_Ret, _Fn, _Args...>::value;
3714template<typename _Ret, typename _Fn, typename... _Args>
3715 inline constexpr bool is_nothrow_invocable_r_v
3716 = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
3717/// @}
3718#endif // __cpp_lib_type_trait_variable_templates
3719
3720#ifdef __cpp_lib_has_unique_object_representations // C++ >= 17 && HAS_UNIQ_OBJ_REP
3721 /// has_unique_object_representations
3722 /// @since C++17
3723 template<typename _Tp>
3724 struct has_unique_object_representations
3725 : bool_constant<__has_unique_object_representations(
3726 remove_cv_t<remove_all_extents_t<_Tp>>
3727 )>
3728 {
3729 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
3730 "template argument must be a complete class or an unbounded array");
3731 };
3732
3733# if __cpp_lib_type_trait_variable_templates // C++ >= 17
3734 /// @ingroup variable_templates
3735 template<typename _Tp>
3736 inline constexpr bool has_unique_object_representations_v
3737 = has_unique_object_representations<_Tp>::value;
3738# endif
3739#endif
3740
3741#ifdef __cpp_lib_is_aggregate // C++ >= 17 && builtin_is_aggregate
3742 /// is_aggregate - true if the type is an aggregate.
3743 /// @since C++17
3744 template<typename _Tp>
3745 struct is_aggregate
3746 : bool_constant<__is_aggregate(remove_cv_t<_Tp>)>
3747 { };
3748
3749# if __cpp_lib_type_trait_variable_templates // C++ >= 17
3750 /** is_aggregate_v - true if the type is an aggregate.
3751 * @ingroup variable_templates
3752 * @since C++17
3753 */
3754 template<typename _Tp>
3755 inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>);
3756# endif
3757#endif
3758
3759 /** * Remove references and cv-qualifiers.
3760 * @since C++20
3761 * @{
3762 */
3763#ifdef __cpp_lib_remove_cvref // C++ >= 20
3764# if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cvref)
3765 template<typename _Tp>
3766 struct remove_cvref
3767 { using type = __remove_cvref(_Tp); };
3768# else
3769 template<typename _Tp>
3770 struct remove_cvref
3771 { using type = typename remove_cv<_Tp>::type; };
3772
3773 template<typename _Tp>
3774 struct remove_cvref<_Tp&>
3775 { using type = typename remove_cv<_Tp>::type; };
3776
3777 template<typename _Tp>
3778 struct remove_cvref<_Tp&&>
3779 { using type = typename remove_cv<_Tp>::type; };
3780# endif
3781
3782 template<typename _Tp>
3783 using remove_cvref_t = typename remove_cvref<_Tp>::type;
3784 /// @}
3785#endif // __cpp_lib_remove_cvref
3786
3787#ifdef __cpp_lib_type_identity // C++ >= 20
3788 /** * Identity metafunction.
3789 * @since C++20
3790 * @{
3791 */
3792 template<typename _Tp>
3793 struct type_identity { using type = _Tp; };
3794
3795 template<typename _Tp>
3796 using type_identity_t = typename type_identity<_Tp>::type;
3797 /// @}
3798#endif
3799
3800#ifdef __cpp_lib_unwrap_ref // C++ >= 20
3801 /** Unwrap a reference_wrapper
3802 * @since C++20
3803 * @{
3804 */
3805 template<typename _Tp>
3806 struct unwrap_reference { using type = _Tp; };
3807
3808 template<typename _Tp>
3809 struct unwrap_reference<reference_wrapper<_Tp>> { using type = _Tp&; };
3810
3811 template<typename _Tp>
3812 using unwrap_reference_t = typename unwrap_reference<_Tp>::type;
3813 /// @}
3814
3815 /** Decay type and if it's a reference_wrapper, unwrap it
3816 * @since C++20
3817 * @{
3818 */
3819 template<typename _Tp>
3820 struct unwrap_ref_decay { using type = unwrap_reference_t<decay_t<_Tp>>; };
3821
3822 template<typename _Tp>
3823 using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type;
3824 /// @}
3825#endif // __cpp_lib_unwrap_ref
3826
3827#ifdef __cpp_lib_bounded_array_traits // C++ >= 20
3828 /// True for a type that is an array of known bound.
3829 /// @ingroup variable_templates
3830 /// @since C++20
3831# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_bounded_array)
3832 template<typename _Tp>
3833 inline constexpr bool is_bounded_array_v = __is_bounded_array(_Tp);
3834# else
3835 template<typename _Tp>
3836 inline constexpr bool is_bounded_array_v = false;
3837
3838 template<typename _Tp, size_t _Size>
3839 inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true;
3840# endif
3841
3842 /// True for a type that is an array of unknown bound.
3843 /// @ingroup variable_templates
3844 /// @since C++20
3845# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unbounded_array)
3846 template<typename _Tp>
3847 inline constexpr bool is_unbounded_array_v = __is_unbounded_array(_Tp);
3848# else
3849 template<typename _Tp>
3850 inline constexpr bool is_unbounded_array_v = false;
3851
3852 template<typename _Tp>
3853 inline constexpr bool is_unbounded_array_v<_Tp[]> = true;
3854# endif
3855
3856 /// True for a type that is an array of known bound.
3857 /// @since C++20
3858 template<typename _Tp>
3859 struct is_bounded_array
3860 : public bool_constant<is_bounded_array_v<_Tp>>
3861 { };
3862
3863 /// True for a type that is an array of unknown bound.
3864 /// @since C++20
3865 template<typename _Tp>
3866 struct is_unbounded_array
3867 : public bool_constant<is_unbounded_array_v<_Tp>>
3868 { };
3869#endif // __cpp_lib_bounded_array_traits
3870
3871#if __has_builtin(__is_layout_compatible) && __cplusplus >= 202002L
3872
3873 /// @since C++20
3874 template<typename _Tp, typename _Up>
3875 struct is_layout_compatible
3876 : bool_constant<__is_layout_compatible(_Tp, _Up)>
3877 { };
3878
3879 /// @ingroup variable_templates
3880 /// @since C++20
3881 template<typename _Tp, typename _Up>
3882 constexpr bool is_layout_compatible_v
3883 = __is_layout_compatible(_Tp, _Up);
3884
3885#if __has_builtin(__builtin_is_corresponding_member)
3886# ifndef __cpp_lib_is_layout_compatible
3887# error "libstdc++ bug: is_corresponding_member and is_layout_compatible are provided but their FTM is not set"
3888# endif
3889
3890 /// @since C++20
3891 template<typename _S1, typename _S2, typename _M1, typename _M2>
3892 constexpr bool
3893 is_corresponding_member(_M1 _S1::*__m1, _M2 _S2::*__m2) noexcept
3894 { return __builtin_is_corresponding_member(__m1, __m2); }
3895#endif
3896#endif
3897
3898#if __has_builtin(__is_pointer_interconvertible_base_of) \
3899 && __cplusplus >= 202002L
3900 /// True if `_Derived` is standard-layout and has a base class of type `_Base`
3901 /// @since C++20
3902 template<typename _Base, typename _Derived>
3903 struct is_pointer_interconvertible_base_of
3904 : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)>
3905 { };
3906
3907 /// @ingroup variable_templates
3908 /// @since C++20
3909 template<typename _Base, typename _Derived>
3910 constexpr bool is_pointer_interconvertible_base_of_v
3911 = __is_pointer_interconvertible_base_of(_Base, _Derived);
3912
3913#if __has_builtin(__builtin_is_pointer_interconvertible_with_class)
3914# ifndef __cpp_lib_is_pointer_interconvertible
3915# error "libstdc++ bug: is_pointer_interconvertible available but FTM is not set"
3916# endif
3917
3918 /// True if `__mp` points to the first member of a standard-layout type
3919 /// @returns true if `s.*__mp` is pointer-interconvertible with `s`
3920 /// @since C++20
3921 template<typename _Tp, typename _Mem>
3922 constexpr bool
3923 is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept
3924 { return __builtin_is_pointer_interconvertible_with_class(__mp); }
3925#endif
3926#endif
3927
3928#ifdef __cpp_lib_is_scoped_enum // C++ >= 23
3929 /// True if the type is a scoped enumeration type.
3930 /// @since C++23
3931
3932# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
3933 template<typename _Tp>
3934 struct is_scoped_enum
3935 : bool_constant<__is_scoped_enum(_Tp)>
3936 { };
3937# else
3938 template<typename _Tp>
3939 struct is_scoped_enum
3940 : false_type
3941 { };
3942
3943 template<typename _Tp>
3944 requires __is_enum(_Tp)
3945 && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete
3946 struct is_scoped_enum<_Tp>
3947 : bool_constant<!requires(_Tp __t, void(*__f)(int)) { __f(__t); }>
3948 { };
3949# endif
3950
3951 /// @ingroup variable_templates
3952 /// @since C++23
3953# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
3954 template<typename _Tp>
3955 inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp);
3956# else
3957 template<typename _Tp>
3958 inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value;
3959# endif
3960#endif
3961
3962#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp
3963 /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
3964 /// direct-initialization, and a temporary object would be bound to
3965 /// the reference, false otherwise.
3966 /// @since C++23
3967 template<typename _Tp, typename _Up>
3968 struct reference_constructs_from_temporary
3969 : public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)>
3970 {
3971 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{})
3972 && std::__is_complete_or_unbounded(__type_identity<_Up>{}),
3973 "template argument must be a complete class or an unbounded array");
3974 };
3975
3976 /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
3977 /// copy-initialization, and a temporary object would be bound to
3978 /// the reference, false otherwise.
3979 /// @since C++23
3980 template<typename _Tp, typename _Up>
3981 struct reference_converts_from_temporary
3982 : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)>
3983 {
3984 static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{})
3985 && std::__is_complete_or_unbounded(__type_identity<_Up>{}),
3986 "template argument must be a complete class or an unbounded array");
3987 };
3988
3989 /// @ingroup variable_templates
3990 /// @since C++23
3991 template<typename _Tp, typename _Up>
3992 inline constexpr bool reference_constructs_from_temporary_v
3993 = reference_constructs_from_temporary<_Tp, _Up>::value;
3994
3995 /// @ingroup variable_templates
3996 /// @since C++23
3997 template<typename _Tp, typename _Up>
3998 inline constexpr bool reference_converts_from_temporary_v
3999 = reference_converts_from_temporary<_Tp, _Up>::value;
4000#endif // __cpp_lib_reference_from_temporary
4001
4002#ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL
4003 /// Returns true only when called during constant evaluation.
4004 /// @since C++20
4005 constexpr inline bool
4006 is_constant_evaluated() noexcept
4007 {
4008#if __cpp_if_consteval >= 202106L
4009 if consteval { return true; } else { return false; }
4010#else
4011 return __builtin_is_constant_evaluated();
4012#endif
4013 }
4014#endif
4015
4016#if __cplusplus >= 202002L
4017 /// @cond undocumented
4018 template<typename _From, typename _To>
4019 using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type;
4020
4021 template<typename _Xp, typename _Yp>
4022 using __cond_res
4023 = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()());
4024
4025 template<typename _Ap, typename _Bp, typename = void>
4026 struct __common_ref_impl
4027 { };
4028
4029 // [meta.trans.other], COMMON-REF(A, B)
4030 template<typename _Ap, typename _Bp>
4031 using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type;
4032
4033 // COND-RES(COPYCV(X, Y) &, COPYCV(Y, X) &)
4034 template<typename _Xp, typename _Yp>
4035 using __condres_cvref
4036 = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>;
4037
4038 // If A and B are both lvalue reference types, ...
4039 template<typename _Xp, typename _Yp>
4040 struct __common_ref_impl<_Xp&, _Yp&, __void_t<__condres_cvref<_Xp, _Yp>>>
4041 : enable_if<is_reference_v<__condres_cvref<_Xp, _Yp>>,
4042 __condres_cvref<_Xp, _Yp>>
4043 { };
4044
4045 // let C be remove_reference_t<COMMON-REF(X&, Y&)>&&
4046 template<typename _Xp, typename _Yp>
4047 using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&;
4048
4049 // If A and B are both rvalue reference types, ...
4050 template<typename _Xp, typename _Yp>
4051 struct __common_ref_impl<_Xp&&, _Yp&&,
4052 _Require<is_convertible<_Xp&&, __common_ref_C<_Xp, _Yp>>,
4053 is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>>
4054 { using type = __common_ref_C<_Xp, _Yp>; };
4055
4056 // let D be COMMON-REF(const X&, Y&)
4057 template<typename _Xp, typename _Yp>
4058 using __common_ref_D = __common_ref<const _Xp&, _Yp&>;
4059
4060 // If A is an rvalue reference and B is an lvalue reference, ...
4061 template<typename _Xp, typename _Yp>
4062 struct __common_ref_impl<_Xp&&, _Yp&,
4063 _Require<is_convertible<_Xp&&, __common_ref_D<_Xp, _Yp>>>>
4064 { using type = __common_ref_D<_Xp, _Yp>; };
4065
4066 // If A is an lvalue reference and B is an rvalue reference, ...
4067 template<typename _Xp, typename _Yp>
4068 struct __common_ref_impl<_Xp&, _Yp&&>
4069 : __common_ref_impl<_Yp&&, _Xp&>
4070 { };
4071 /// @endcond
4072
4073 template<typename _Tp, typename _Up,
4074 template<typename> class _TQual, template<typename> class _UQual>
4075 struct basic_common_reference
4076 { };
4077
4078 /// @cond undocumented
4079 template<typename _Tp>
4080 struct __xref
4081 { template<typename _Up> using __type = __copy_cv<_Tp, _Up>; };
4082
4083 template<typename _Tp>
4084 struct __xref<_Tp&>
4085 { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&; };
4086
4087 template<typename _Tp>
4088 struct __xref<_Tp&&>
4089 { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&&; };
4090
4091 template<typename _Tp1, typename _Tp2>
4092 using __basic_common_ref
4093 = typename basic_common_reference<remove_cvref_t<_Tp1>,
4094 remove_cvref_t<_Tp2>,
4095 __xref<_Tp1>::template __type,
4096 __xref<_Tp2>::template __type>::type;
4097 /// @endcond
4098
4099 template<typename... _Tp>
4100 struct common_reference;
4101
4102 template<typename... _Tp>
4103 using common_reference_t = typename common_reference<_Tp...>::type;
4104
4105 // If sizeof...(T) is zero, there shall be no member type.
4106 template<>
4107 struct common_reference<>
4108 { };
4109
4110 // If sizeof...(T) is one ...
4111 template<typename _Tp0>
4112 struct common_reference<_Tp0>
4113 { using type = _Tp0; };
4114
4115 /// @cond undocumented
4116 template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void>
4117 struct __common_reference_impl
4118 : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1>
4119 { };
4120
4121 // If sizeof...(T) is two ...
4122 template<typename _Tp1, typename _Tp2>
4123 struct common_reference<_Tp1, _Tp2>
4124 : __common_reference_impl<_Tp1, _Tp2>
4125 { };
4126
4127 // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ...
4128 template<typename _Tp1, typename _Tp2>
4129 struct __common_reference_impl<_Tp1&, _Tp2&, 1,
4130 void_t<__common_ref<_Tp1&, _Tp2&>>>
4131 { using type = __common_ref<_Tp1&, _Tp2&>; };
4132
4133 template<typename _Tp1, typename _Tp2>
4134 struct __common_reference_impl<_Tp1&&, _Tp2&&, 1,
4135 void_t<__common_ref<_Tp1&&, _Tp2&&>>>
4136 { using type = __common_ref<_Tp1&&, _Tp2&&>; };
4137
4138 template<typename _Tp1, typename _Tp2>
4139 struct __common_reference_impl<_Tp1&, _Tp2&&, 1,
4140 void_t<__common_ref<_Tp1&, _Tp2&&>>>
4141 { using type = __common_ref<_Tp1&, _Tp2&&>; };
4142
4143 template<typename _Tp1, typename _Tp2>
4144 struct __common_reference_impl<_Tp1&&, _Tp2&, 1,
4145 void_t<__common_ref<_Tp1&&, _Tp2&>>>
4146 { using type = __common_ref<_Tp1&&, _Tp2&>; };
4147
4148 // Otherwise, if basic_common_reference<...>::type is well-formed, ...
4149 template<typename _Tp1, typename _Tp2>
4150 struct __common_reference_impl<_Tp1, _Tp2, 2,
4151 void_t<__basic_common_ref<_Tp1, _Tp2>>>
4152 { using type = __basic_common_ref<_Tp1, _Tp2>; };
4153
4154 // Otherwise, if COND-RES(T1, T2) is well-formed, ...
4155 template<typename _Tp1, typename _Tp2>
4156 struct __common_reference_impl<_Tp1, _Tp2, 3,
4157 void_t<__cond_res<_Tp1, _Tp2>>>
4158 { using type = __cond_res<_Tp1, _Tp2>; };
4159
4160 // Otherwise, if common_type_t<T1, T2> is well-formed, ...
4161 template<typename _Tp1, typename _Tp2>
4162 struct __common_reference_impl<_Tp1, _Tp2, 4,
4163 void_t<common_type_t<_Tp1, _Tp2>>>
4164 { using type = common_type_t<_Tp1, _Tp2>; };
4165
4166 // Otherwise, there shall be no member type.
4167 template<typename _Tp1, typename _Tp2>
4168 struct __common_reference_impl<_Tp1, _Tp2, 5, void>
4169 { };
4170
4171 // Otherwise, if sizeof...(T) is greater than two, ...
4172 template<typename _Tp1, typename _Tp2, typename... _Rest>
4173 struct common_reference<_Tp1, _Tp2, _Rest...>
4174 : __common_type_fold<common_reference<_Tp1, _Tp2>,
4175 __common_type_pack<_Rest...>>
4176 { };
4177
4178 // Reuse __common_type_fold for common_reference<T1, T2, Rest...>
4179 template<typename _Tp1, typename _Tp2, typename... _Rest>
4180 struct __common_type_fold<common_reference<_Tp1, _Tp2>,
4181 __common_type_pack<_Rest...>,
4182 void_t<common_reference_t<_Tp1, _Tp2>>>
4183 : public common_reference<common_reference_t<_Tp1, _Tp2>, _Rest...>
4184 { };
4185 /// @endcond
4186
4187#endif // C++2a
4188
4189 /// @} group metaprogramming
4190
4191_GLIBCXX_END_NAMESPACE_VERSION
4192} // namespace std
4193} // extern "C++"
4194
4195#endif // C++11
4196
4197#endif // _GLIBCXX_TYPE_TRAITS