libstdc++: cpp_type_traits.h Source File

libstdc++

cpp_type_traits.h
Go to the documentation of this file.
1// The -*- C++ -*- type traits classes for internal use in libstdc++
2
3// Copyright (C) 2000-2026 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 bits/cpp_type_traits.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{ext/type_traits.h}
28 */
29
30// Written by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
31
32#ifndef _CPP_TYPE_TRAITS_H
33#define _CPP_TYPE_TRAITS_H 1
34
35#ifdef _GLIBCXX_SYSHDR
36#pragma GCC system_header
37#endif
38
39#include <bits/c++config.h>
40#include <bits/version.h>
41#if __glibcxx_type_trait_variable_templates
42# include <type_traits> // is_same_v, is_integral_v
43#endif
44
45#pragma GCC diagnostic push
46#pragma GCC diagnostic ignored "-Wlong-long"
47
48//
49// This file provides some compile-time information about various types.
50// These representations were designed, on purpose, to be constant-expressions
51// and not types as found in <bits/type_traits.h>. In particular, they
52// can be used in control structures and the optimizer hopefully will do
53// the obvious thing.
54//
55// Why integral expressions, and not functions nor types?
56// Firstly, these compile-time entities are used as template-arguments
57// so function return values won't work: We need compile-time entities.
58// We're left with types and constant integral expressions.
59// Secondly, from the point of view of ease of use, type-based compile-time
60// information is -not- *that* convenient. One has to write lots of
61// overloaded functions and to hope that the compiler will select the right
62// one. As a net effect, the overall structure isn't very clear at first
63// glance.
64// Thirdly, partial ordering and overload resolution (of function templates)
65// is highly costly in terms of compiler-resource. It is a Good Thing to
66// keep these resource consumption as least as possible.
67//
68// See valarray_array.h for a case use.
69//
70// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06.
71//
72// Update 2005: types are also provided and <bits/type_traits.h> has been
73// removed.
74//
75
76extern "C++" {
77
78namespace std _GLIBCXX_VISIBILITY(default)
79{
80_GLIBCXX_BEGIN_NAMESPACE_VERSION
81
82 struct __true_type { };
83 struct __false_type { };
84
85 template<bool>
86 struct __truth_type
87 { typedef __false_type __type; };
88
89 template<>
90 struct __truth_type<true>
91 { typedef __true_type __type; };
92
93 // N.B. The conversions to bool are needed due to the issue
94 // explained in c++/19404.
95 template<class _Sp, class _Tp>
96 struct __traitor
97 {
98 enum { __value = bool(_Sp::__value) || bool(_Tp::__value) };
99 typedef typename __truth_type<__value>::__type __type;
100 };
101
102 // Compare for equality of types.
103 template<typename, typename>
104 struct __are_same
105 {
106 enum { __value = 0 };
107 typedef __false_type __type;
108 };
109
110 template<typename _Tp>
111 struct __are_same<_Tp, _Tp>
112 {
113 enum { __value = 1 };
114 typedef __true_type __type;
115 };
116
117 //
118 // Integer types
119 //
120 template<typename _Tp>
121 struct __is_integer
122 {
123 enum { __value = 0 };
124 typedef __false_type __type;
125 };
126
127 // Explicit specializations for the standard integer types.
128 // Up to four target-specific __int<N> types are supported as well.
129 template<>
130 struct __is_integer<bool>
131 {
132 enum { __value = 1 };
133 typedef __true_type __type;
134 };
135
136 template<>
137 struct __is_integer<char>
138 {
139 enum { __value = 1 };
140 typedef __true_type __type;
141 };
142
143 template<>
144 struct __is_integer<signed char>
145 {
146 enum { __value = 1 };
147 typedef __true_type __type;
148 };
149
150 template<>
151 struct __is_integer<unsigned char>
152 {
153 enum { __value = 1 };
154 typedef __true_type __type;
155 };
156
157# ifdef __WCHAR_TYPE__
158 template<>
159 struct __is_integer<wchar_t>
160 {
161 enum { __value = 1 };
162 typedef __true_type __type;
163 };
164# endif
165
166#ifdef _GLIBCXX_USE_CHAR8_T
167 template<>
168 struct __is_integer<char8_t>
169 {
170 enum { __value = 1 };
171 typedef __true_type __type;
172 };
173#endif
174
175#if __cplusplus >= 201103L
176 template<>
177 struct __is_integer<char16_t>
178 {
179 enum { __value = 1 };
180 typedef __true_type __type;
181 };
182
183 template<>
184 struct __is_integer<char32_t>
185 {
186 enum { __value = 1 };
187 typedef __true_type __type;
188 };
189#endif
190
191 template<>
192 struct __is_integer<short>
193 {
194 enum { __value = 1 };
195 typedef __true_type __type;
196 };
197
198 template<>
199 struct __is_integer<unsigned short>
200 {
201 enum { __value = 1 };
202 typedef __true_type __type;
203 };
204
205 template<>
206 struct __is_integer<int>
207 {
208 enum { __value = 1 };
209 typedef __true_type __type;
210 };
211
212 template<>
213 struct __is_integer<unsigned int>
214 {
215 enum { __value = 1 };
216 typedef __true_type __type;
217 };
218
219 template<>
220 struct __is_integer<long>
221 {
222 enum { __value = 1 };
223 typedef __true_type __type;
224 };
225
226 template<>
227 struct __is_integer<unsigned long>
228 {
229 enum { __value = 1 };
230 typedef __true_type __type;
231 };
232
233 template<>
234 struct __is_integer<long long>
235 {
236 enum { __value = 1 };
237 typedef __true_type __type;
238 };
239
240 template<>
241 struct __is_integer<unsigned long long>
242 {
243 enum { __value = 1 };
244 typedef __true_type __type;
245 };
246
247#define __INT_N(TYPE) \
248 __extension__ \
249 template<> \
250 struct __is_integer<TYPE> \
251 { \
252 enum { __value = 1 }; \
253 typedef __true_type __type; \
254 }; \
255 __extension__ \
256 template<> \
257 struct __is_integer<unsigned TYPE> \
258 { \
259 enum { __value = 1 }; \
260 typedef __true_type __type; \
261 };
262
263#ifdef __GLIBCXX_TYPE_INT_N_0
264__INT_N(__GLIBCXX_TYPE_INT_N_0)
265#endif
266#ifdef __GLIBCXX_TYPE_INT_N_1
267__INT_N(__GLIBCXX_TYPE_INT_N_1)
268#endif
269#ifdef __GLIBCXX_TYPE_INT_N_2
270__INT_N(__GLIBCXX_TYPE_INT_N_2)
271#endif
272#ifdef __GLIBCXX_TYPE_INT_N_3
273__INT_N(__GLIBCXX_TYPE_INT_N_3)
274#endif
275
276#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
277// In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128,
278// but we want to always treat signed/unsigned __int128 as integral types.
279__INT_N(__int128)
280#endif
281
282#undef __INT_N
283
284 //
285 // Floating point types
286 //
287 template<typename _Tp>
288 struct __is_floating
289 {
290 enum { __value = 0 };
291 typedef __false_type __type;
292 };
293
294 // three specializations (float, double and 'long double')
295 template<>
296 struct __is_floating<float>
297 {
298 enum { __value = 1 };
299 typedef __true_type __type;
300 };
301
302 template<>
303 struct __is_floating<double>
304 {
305 enum { __value = 1 };
306 typedef __true_type __type;
307 };
308
309 template<>
310 struct __is_floating<long double>
311 {
312 enum { __value = 1 };
313 typedef __true_type __type;
314 };
315
316#ifdef _GLIBCXX_USE_FLOAT128
317 template<>
318 struct __is_floating<__float128>
319 {
320 enum { __value = 1 };
321 typedef __true_type __type;
322 };
323#endif
324
325#ifdef __STDCPP_FLOAT16_T__
326 template<>
327 struct __is_floating<_Float16>
328 {
329 enum { __value = 1 };
330 typedef __true_type __type;
331 };
332#endif
333
334#ifdef __STDCPP_FLOAT32_T__
335 template<>
336 struct __is_floating<_Float32>
337 {
338 enum { __value = 1 };
339 typedef __true_type __type;
340 };
341#endif
342
343#ifdef __STDCPP_FLOAT64_T__
344 template<>
345 struct __is_floating<_Float64>
346 {
347 enum { __value = 1 };
348 typedef __true_type __type;
349 };
350#endif
351
352#ifdef __STDCPP_FLOAT128_T__
353 template<>
354 struct __is_floating<_Float128>
355 {
356 enum { __value = 1 };
357 typedef __true_type __type;
358 };
359#endif
360
361#ifdef __STDCPP_BFLOAT16_T__
362 template<>
363 struct __is_floating<__gnu_cxx::__bfloat16_t>
364 {
365 enum { __value = 1 };
366 typedef __true_type __type;
367 };
368#endif
369
370 //
371 // An arithmetic type is an integer type or a floating point type
372 //
373 template<typename _Tp>
374 struct __is_arithmetic
375 : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> >
376 { };
377
378 //
379 // For use in std::copy and std::find overloads for streambuf iterators.
380 //
381 template<typename _Tp>
382 struct __is_char
383 {
384 enum { __value = 0 };
385 typedef __false_type __type;
386 };
387
388 template<>
389 struct __is_char<char>
390 {
391 enum { __value = 1 };
392 typedef __true_type __type;
393 };
394
395#ifdef __WCHAR_TYPE__
396 template<>
397 struct __is_char<wchar_t>
398 {
399 enum { __value = 1 };
400 typedef __true_type __type;
401 };
402#endif
403
404 template<typename _Tp>
405 struct __is_byte
406 {
407 enum { __value = 0 };
408 typedef __false_type __type;
409 };
410
411 template<>
412 struct __is_byte<char>
413 {
414 enum { __value = 1 };
415 typedef __true_type __type;
416 };
417
418 template<>
419 struct __is_byte<signed char>
420 {
421 enum { __value = 1 };
422 typedef __true_type __type;
423 };
424
425 template<>
426 struct __is_byte<unsigned char>
427 {
428 enum { __value = 1 };
429 typedef __true_type __type;
430 };
431
432#ifdef __glibcxx_byte // C++ >= 17
433 enum class byte : unsigned char;
434
435 template<>
436 struct __is_byte<byte>
437 {
438 enum { __value = 1 };
439 typedef __true_type __type;
440 };
441#endif // C++17
442
443#ifdef _GLIBCXX_USE_CHAR8_T
444 template<>
445 struct __is_byte<char8_t>
446 {
447 enum { __value = 1 };
448 typedef __true_type __type;
449 };
450#endif
451
452 // A type that is safe for use with memcpy, memmove, memcmp etc.
453 template<typename _Tp>
454 struct __is_nonvolatile_trivially_copyable
455 {
456 enum { __value = __is_trivially_copyable(_Tp) };
457 };
458
459 // Cannot use memcpy/memmove/memcmp on volatile types even if they are
460 // trivially copyable, so ensure __memcpyable<volatile int*, volatile int*>
461 // and similar will be false.
462 template<typename _Tp>
463 struct __is_nonvolatile_trivially_copyable<volatile _Tp>
464 {
465 enum { __value = 0 };
466 };
467
468 // Whether two iterator types can be used with memcpy/memmove.
469 template<typename _OutputIter, typename _InputIter>
470 struct __memcpyable
471 {
472 enum { __value = 0 };
473 };
474
475 // Allow memcpy when source and destination are pointers to the same type.
476 template<typename _Tp>
477 struct __memcpyable<_Tp*, _Tp*>
478 : __is_nonvolatile_trivially_copyable<_Tp>
479 { };
480
481 // Source pointer can be const.
482 template<typename _Tp>
483 struct __memcpyable<_Tp*, const _Tp*>
484 : __is_nonvolatile_trivially_copyable<_Tp>
485 { };
486
487 template<typename _Tp> struct __memcpyable_integer;
488
489 // For heterogeneous types, allow memcpy between equal-sized integers.
490 // N.B. we cannot do the same for equal-sized enums, they're not assignable.
491 // We cannot do it for pointers, because derived-to-base can adjust offset.
492 template<typename _Tp, typename _Up>
493 struct __memcpyable<_Tp*, _Up*>
494 {
495 enum {
496 __value = __memcpyable_integer<_Tp>::__width != 0
497 && ((int)__memcpyable_integer<_Tp>::__width
498 == (int)__memcpyable_integer<_Up>::__width)
499 };
500 };
501
502 // Specialization for const U* because __is_integer<const U> is never true.
503 template<typename _Tp, typename _Up>
504 struct __memcpyable<_Tp*, const _Up*>
505 : __memcpyable<_Tp*, _Up*>
506 { };
507
508 template<typename _Tp>
509 struct __memcpyable_integer
510 {
511 enum {
512 __width = __is_integer<_Tp>::__value ? (sizeof(_Tp) * __CHAR_BIT__) : 0
513 };
514 };
515
516 // Cannot memcpy volatile memory.
517 template<typename _Tp>
518 struct __memcpyable_integer<volatile _Tp>
519 { enum { __width = 0 }; };
520
521 // Assigning an integer to bool needs to convert all non-zero values to true
522 // so it is not a memcpyable integer.
523 // __memcpyable<bool*, bool*> is still true though.
524 template<>
525 struct __memcpyable_integer<bool>
526 { enum { __width = 0 }; };
527
528 // Specializations for __intNN types with padding bits.
529#if defined __GLIBCXX_TYPE_INT_N_0 && __GLIBCXX_BITSIZE_INT_N_0 % __CHAR_BIT__
530 __extension__
531 template<>
532 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_0>
533 { enum { __width = __GLIBCXX_BITSIZE_INT_N_0 }; };
534 __extension__
535 template<>
536 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_0>
537 { enum { __width = __GLIBCXX_BITSIZE_INT_N_0 }; };
538#endif
539#if defined __GLIBCXX_TYPE_INT_N_1 && __GLIBCXX_BITSIZE_INT_N_1 % __CHAR_BIT__
540 __extension__
541 template<>
542 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_1>
543 { enum { __width = __GLIBCXX_BITSIZE_INT_N_1 }; };
544 __extension__
545 template<>
546 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_1>
547 { enum { __width = __GLIBCXX_BITSIZE_INT_N_1 }; };
548#endif
549#if defined __GLIBCXX_TYPE_INT_N_2 && __GLIBCXX_BITSIZE_INT_N_2 % __CHAR_BIT__
550 __extension__
551 template<>
552 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_2>
553 { enum { __width = __GLIBCXX_BITSIZE_INT_N_2 }; };
554 __extension__
555 template<>
556 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_2>
557 { enum { __width = __GLIBCXX_BITSIZE_INT_N_2 }; };
558#endif
559#if defined __GLIBCXX_TYPE_INT_N_3 && __GLIBCXX_BITSIZE_INT_N_3 % __CHAR_BIT__
560 __extension__
561 template<>
562 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_3>
563 { enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; };
564 __extension__
565 template<>
566 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_3>
567 { enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; };
568#endif
569
570#if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64
571 template<>
572 struct __memcpyable<double*, long double*> { enum { __value = true }; };
573 template<>
574 struct __memcpyable<long double*, double*> { enum { __value = true }; };
575#endif
576
577#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
578 template<>
579 struct __memcpyable<_Float32*, float*> { enum { __value = true }; };
580 template<>
581 struct __memcpyable<float*, _Float32*> { enum { __value = true }; };
582#endif
583
584#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
585 template<>
586 struct __memcpyable<_Float64*, double*> { enum { __value = true }; };
587 template<>
588 struct __memcpyable<double*, _Float64*> { enum { __value = true }; };
589#endif
590
591#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
592 template<>
593 struct __memcpyable<_Float128*, long double*> { enum { __value = true }; };
594 template<>
595 struct __memcpyable<long double*, _Float128*> { enum { __value = true }; };
596#endif
597
598 // Whether two iterator types can be used with memcmp.
599 // This trait only says it's well-formed to use memcmp, not that it
600 // gives the right answer for a given algorithm. So for example, std::equal
601 // needs to add additional checks that the types are integers or pointers,
602 // because other trivially copyable types can overload operator==.
603 template<typename _Iter1, typename _Iter2>
604 struct __memcmpable
605 {
606 enum { __value = 0 };
607 };
608
609 // OK to use memcmp with pointers to trivially copyable types.
610 template<typename _Tp>
611 struct __memcmpable<_Tp*, _Tp*>
612 : __is_nonvolatile_trivially_copyable<_Tp>
613 { };
614
615 template<typename _Tp>
616 struct __memcmpable<const _Tp*, _Tp*>
617 : __is_nonvolatile_trivially_copyable<_Tp>
618 { };
619
620 template<typename _Tp>
621 struct __memcmpable<_Tp*, const _Tp*>
622 : __is_nonvolatile_trivially_copyable<_Tp>
623 { };
624
625 // Whether memcmp can be used to determine ordering for a type
626 // e.g. in std::lexicographical_compare or three-way comparisons.
627 // True for unsigned integer-like types where comparing each byte in turn
628 // as an unsigned char yields the right result. This is true for all
629 // unsigned integers on big endian targets, but only unsigned narrow
630 // character types (and std::byte) on little endian targets.
631 template<typename _Tp, bool _TreatAsBytes =
632#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
633 __is_integer<_Tp>::__value
634#else
635 __is_byte<_Tp>::__value
636#endif
637 >
638 struct __is_memcmp_ordered
639 {
640 static const bool __value = _Tp(-1) > _Tp(1); // is unsigned
641 };
642
643 template<typename _Tp>
644 struct __is_memcmp_ordered<_Tp, false>
645 {
646 static const bool __value = false;
647 };
648
649 // Whether two types can be compared using memcmp.
650 template<typename _Tp, typename _Up, bool = sizeof(_Tp) == sizeof(_Up)>
651 struct __is_memcmp_ordered_with
652 {
653 static const bool __value = __is_memcmp_ordered<_Tp>::__value
654 && __is_memcmp_ordered<_Up>::__value;
655 };
656
657 template<typename _Tp, typename _Up>
658 struct __is_memcmp_ordered_with<_Tp, _Up, false>
659 {
660 static const bool __value = false;
661 };
662
663#if __cplusplus >= 201703L
664#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
665 // std::byte is not an integer, but it can be compared using memcmp.
666 template<>
667 struct __is_memcmp_ordered<std::byte, false>
668 { static constexpr bool __value = true; };
669#endif
670
671 // std::byte can only be compared to itself, not to other types.
672 template<>
673 struct __is_memcmp_ordered_with<std::byte, std::byte, true>
674 { static constexpr bool __value = true; };
675
676 template<typename _Tp, bool _SameSize>
677 struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize>
678 { static constexpr bool __value = false; };
679
680 template<typename _Up, bool _SameSize>
681 struct __is_memcmp_ordered_with<std::byte, _Up, _SameSize>
682 { static constexpr bool __value = false; };
683#endif
684
685#if __glibcxx_type_trait_variable_templates
686 template<typename _ValT, typename _Tp>
687 constexpr bool __can_use_memchr_for_find
688 // Can only use memchr to search for narrow characters and std::byte.
689 = __is_byte<_ValT>::__value
690 // And only if the value to find is an integer (or is also std::byte).
691 && (is_same_v<_Tp, _ValT> || is_integral_v<_Tp>);
692#endif
693
694 //
695 // Move iterator type
696 //
697 template<typename _Tp>
698 struct __is_move_iterator
699 {
700 enum { __value = 0 };
701 typedef __false_type __type;
702 };
703
704 // Fallback implementation of the function in bits/stl_iterator.h used to
705 // remove the move_iterator wrapper.
706 template<typename _Iterator>
707 _GLIBCXX20_CONSTEXPR
708 inline _Iterator
709 __miter_base(_Iterator __it)
710 { return __it; }
711
712_GLIBCXX_END_NAMESPACE_VERSION
713} // namespace
714} // extern "C++"
715
716#pragma GCC diagnostic pop
717
718#endif //_CPP_TYPE_TRAITS_H
type_traits
version.h
c++config.h
std
ISO C++ entities toplevel namespace is std.