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-2024 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#undef __INT_N
277
278 //
279 // Floating point types
280 //
281 template<typename _Tp>
282 struct __is_floating
283 {
284 enum { __value = 0 };
285 typedef __false_type __type;
286 };
287
288 // three specializations (float, double and 'long double')
289 template<>
290 struct __is_floating<float>
291 {
292 enum { __value = 1 };
293 typedef __true_type __type;
294 };
295
296 template<>
297 struct __is_floating<double>
298 {
299 enum { __value = 1 };
300 typedef __true_type __type;
301 };
302
303 template<>
304 struct __is_floating<long double>
305 {
306 enum { __value = 1 };
307 typedef __true_type __type;
308 };
309
310#ifdef __STDCPP_FLOAT16_T__
311 template<>
312 struct __is_floating<_Float16>
313 {
314 enum { __value = 1 };
315 typedef __true_type __type;
316 };
317#endif
318
319#ifdef __STDCPP_FLOAT32_T__
320 template<>
321 struct __is_floating<_Float32>
322 {
323 enum { __value = 1 };
324 typedef __true_type __type;
325 };
326#endif
327
328#ifdef __STDCPP_FLOAT64_T__
329 template<>
330 struct __is_floating<_Float64>
331 {
332 enum { __value = 1 };
333 typedef __true_type __type;
334 };
335#endif
336
337#ifdef __STDCPP_FLOAT128_T__
338 template<>
339 struct __is_floating<_Float128>
340 {
341 enum { __value = 1 };
342 typedef __true_type __type;
343 };
344#endif
345
346#ifdef __STDCPP_BFLOAT16_T__
347 template<>
348 struct __is_floating<__gnu_cxx::__bfloat16_t>
349 {
350 enum { __value = 1 };
351 typedef __true_type __type;
352 };
353#endif
354
355 //
356 // An arithmetic type is an integer type or a floating point type
357 //
358 template<typename _Tp>
359 struct __is_arithmetic
360 : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> >
361 { };
362
363 //
364 // For use in std::copy and std::find overloads for streambuf iterators.
365 //
366 template<typename _Tp>
367 struct __is_char
368 {
369 enum { __value = 0 };
370 typedef __false_type __type;
371 };
372
373 template<>
374 struct __is_char<char>
375 {
376 enum { __value = 1 };
377 typedef __true_type __type;
378 };
379
380#ifdef __WCHAR_TYPE__
381 template<>
382 struct __is_char<wchar_t>
383 {
384 enum { __value = 1 };
385 typedef __true_type __type;
386 };
387#endif
388
389 template<typename _Tp>
390 struct __is_byte
391 {
392 enum { __value = 0 };
393 typedef __false_type __type;
394 };
395
396 template<>
397 struct __is_byte<char>
398 {
399 enum { __value = 1 };
400 typedef __true_type __type;
401 };
402
403 template<>
404 struct __is_byte<signed char>
405 {
406 enum { __value = 1 };
407 typedef __true_type __type;
408 };
409
410 template<>
411 struct __is_byte<unsigned char>
412 {
413 enum { __value = 1 };
414 typedef __true_type __type;
415 };
416
417#ifdef __glibcxx_byte // C++ >= 17
418 enum class byte : unsigned char;
419
420 template<>
421 struct __is_byte<byte>
422 {
423 enum { __value = 1 };
424 typedef __true_type __type;
425 };
426#endif // C++17
427
428#ifdef _GLIBCXX_USE_CHAR8_T
429 template<>
430 struct __is_byte<char8_t>
431 {
432 enum { __value = 1 };
433 typedef __true_type __type;
434 };
435#endif
436
437 // A type that is safe for use with memcpy, memmove, memcmp etc.
438 template<typename _Tp>
439 struct __is_nonvolatile_trivially_copyable
440 {
441 enum { __value = __is_trivially_copyable(_Tp) };
442 };
443
444 // Cannot use memcpy/memmove/memcmp on volatile types even if they are
445 // trivially copyable, so ensure __memcpyable<volatile int*, volatile int*>
446 // and similar will be false.
447 template<typename _Tp>
448 struct __is_nonvolatile_trivially_copyable<volatile _Tp>
449 {
450 enum { __value = 0 };
451 };
452
453 // Whether two iterator types can be used with memcpy/memmove.
454 template<typename _OutputIter, typename _InputIter>
455 struct __memcpyable
456 {
457 enum { __value = 0 };
458 };
459
460 // Allow memcpy when source and destination are pointers to the same type.
461 template<typename _Tp>
462 struct __memcpyable<_Tp*, _Tp*>
463 : __is_nonvolatile_trivially_copyable<_Tp>
464 { };
465
466 // Source pointer can be const.
467 template<typename _Tp>
468 struct __memcpyable<_Tp*, const _Tp*>
469 : __is_nonvolatile_trivially_copyable<_Tp>
470 { };
471
472 template<typename _Tp> struct __memcpyable_integer;
473
474 // For heterogeneous types, allow memcpy between equal-sized integers.
475 // N.B. we cannot do the same for equal-sized enums, they're not assignable.
476 // We cannot do it for pointers, because derived-to-base can adjust offset.
477 template<typename _Tp, typename _Up>
478 struct __memcpyable<_Tp*, _Up*>
479 {
480 enum {
481 __value = __memcpyable_integer<_Tp>::__width != 0
482 && ((int)__memcpyable_integer<_Tp>::__width
483 == (int)__memcpyable_integer<_Up>::__width)
484 };
485 };
486
487 // Specialization for const U* because __is_integer<const U> is never true.
488 template<typename _Tp, typename _Up>
489 struct __memcpyable<_Tp*, const _Up*>
490 : __memcpyable<_Tp*, _Up*>
491 { };
492
493 template<typename _Tp>
494 struct __memcpyable_integer
495 {
496 enum {
497 __width = __is_integer<_Tp>::__value ? (sizeof(_Tp) * __CHAR_BIT__) : 0
498 };
499 };
500
501 // Cannot memcpy volatile memory.
502 template<typename _Tp>
503 struct __memcpyable_integer<volatile _Tp>
504 { enum { __width = 0 }; };
505
506 // Specializations for __intNN types with padding bits.
507#if defined __GLIBCXX_TYPE_INT_N_0 && __GLIBCXX_BITSIZE_INT_N_0 % __CHAR_BIT__
508 __extension__
509 template<>
510 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_0>
511 { enum { __width = __GLIBCXX_BITSIZE_INT_N_0 }; };
512 __extension__
513 template<>
514 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_0>
515 { enum { __width = __GLIBCXX_BITSIZE_INT_N_0 }; };
516#endif
517#if defined __GLIBCXX_TYPE_INT_N_1 && __GLIBCXX_BITSIZE_INT_N_1 % __CHAR_BIT__
518 __extension__
519 template<>
520 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_1>
521 { enum { __width = __GLIBCXX_BITSIZE_INT_N_1 }; };
522 __extension__
523 template<>
524 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_1>
525 { enum { __width = __GLIBCXX_BITSIZE_INT_N_1 }; };
526#endif
527#if defined __GLIBCXX_TYPE_INT_N_2 && __GLIBCXX_BITSIZE_INT_N_2 % __CHAR_BIT__
528 __extension__
529 template<>
530 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_2>
531 { enum { __width = __GLIBCXX_BITSIZE_INT_N_2 }; };
532 __extension__
533 template<>
534 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_2>
535 { enum { __width = __GLIBCXX_BITSIZE_INT_N_2 }; };
536#endif
537#if defined __GLIBCXX_TYPE_INT_N_3 && __GLIBCXX_BITSIZE_INT_N_3 % __CHAR_BIT__
538 __extension__
539 template<>
540 struct __memcpyable_integer<__GLIBCXX_TYPE_INT_N_3>
541 { enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; };
542 __extension__
543 template<>
544 struct __memcpyable_integer<unsigned __GLIBCXX_TYPE_INT_N_3>
545 { enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; };
546#endif
547
548#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
549 // In strict modes __is_integer<__int128> is false,
550 // but we want to allow memcpy between signed/unsigned __int128.
551 __extension__
552 template<>
553 struct __memcpyable_integer<__int128> { enum { __width = 128 }; };
554 __extension__
555 template<>
556 struct __memcpyable_integer<unsigned __int128> { enum { __width = 128 }; };
557#endif
558
559#if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64
560 template<>
561 struct __memcpyable<double*, long double*> { enum { __value = true }; };
562 template<>
563 struct __memcpyable<long double*, double*> { enum { __value = true }; };
564#endif
565
566#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
567 template<>
568 struct __memcpyable<_Float32*, float*> { enum { __value = true }; };
569 template<>
570 struct __memcpyable<float*, _Float32*> { enum { __value = true }; };
571#endif
572
573#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
574 template<>
575 struct __memcpyable<_Float64*, double*> { enum { __value = true }; };
576 template<>
577 struct __memcpyable<double*, _Float64*> { enum { __value = true }; };
578#endif
579
580#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
581 template<>
582 struct __memcpyable<_Float128*, long double*> { enum { __value = true }; };
583 template<>
584 struct __memcpyable<long double*, _Float128*> { enum { __value = true }; };
585#endif
586
587 // Whether two iterator types can be used with memcmp.
588 // This trait only says it's well-formed to use memcmp, not that it
589 // gives the right answer for a given algorithm. So for example, std::equal
590 // needs to add additional checks that the types are integers or pointers,
591 // because other trivially copyable types can overload operator==.
592 template<typename _Iter1, typename _Iter2>
593 struct __memcmpable
594 {
595 enum { __value = 0 };
596 };
597
598 // OK to use memcmp with pointers to trivially copyable types.
599 template<typename _Tp>
600 struct __memcmpable<_Tp*, _Tp*>
601 : __is_nonvolatile_trivially_copyable<_Tp>
602 { };
603
604 template<typename _Tp>
605 struct __memcmpable<const _Tp*, _Tp*>
606 : __is_nonvolatile_trivially_copyable<_Tp>
607 { };
608
609 template<typename _Tp>
610 struct __memcmpable<_Tp*, const _Tp*>
611 : __is_nonvolatile_trivially_copyable<_Tp>
612 { };
613
614 // Whether memcmp can be used to determine ordering for a type
615 // e.g. in std::lexicographical_compare or three-way comparisons.
616 // True for unsigned integer-like types where comparing each byte in turn
617 // as an unsigned char yields the right result. This is true for all
618 // unsigned integers on big endian targets, but only unsigned narrow
619 // character types (and std::byte) on little endian targets.
620 template<typename _Tp, bool _TreatAsBytes =
621#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
622 __is_integer<_Tp>::__value
623#else
624 __is_byte<_Tp>::__value
625#endif
626 >
627 struct __is_memcmp_ordered
628 {
629 static const bool __value = _Tp(-1) > _Tp(1); // is unsigned
630 };
631
632 template<typename _Tp>
633 struct __is_memcmp_ordered<_Tp, false>
634 {
635 static const bool __value = false;
636 };
637
638 // Whether two types can be compared using memcmp.
639 template<typename _Tp, typename _Up, bool = sizeof(_Tp) == sizeof(_Up)>
640 struct __is_memcmp_ordered_with
641 {
642 static const bool __value = __is_memcmp_ordered<_Tp>::__value
643 && __is_memcmp_ordered<_Up>::__value;
644 };
645
646 template<typename _Tp, typename _Up>
647 struct __is_memcmp_ordered_with<_Tp, _Up, false>
648 {
649 static const bool __value = false;
650 };
651
652#if __cplusplus >= 201703L
653#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
654 // std::byte is not an integer, but it can be compared using memcmp.
655 template<>
656 struct __is_memcmp_ordered<std::byte, false>
657 { static constexpr bool __value = true; };
658#endif
659
660 // std::byte can only be compared to itself, not to other types.
661 template<>
662 struct __is_memcmp_ordered_with<std::byte, std::byte, true>
663 { static constexpr bool __value = true; };
664
665 template<typename _Tp, bool _SameSize>
666 struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize>
667 { static constexpr bool __value = false; };
668
669 template<typename _Up, bool _SameSize>
670 struct __is_memcmp_ordered_with<std::byte, _Up, _SameSize>
671 { static constexpr bool __value = false; };
672#endif
673
674#if __glibcxx_type_trait_variable_templates
675 template<typename _ValT, typename _Tp>
676 constexpr bool __can_use_memchr_for_find
677 // Can only use memchr to search for narrow characters and std::byte.
678 = __is_byte<_ValT>::__value
679 // And only if the value to find is an integer (or is also std::byte).
680 && (is_same_v<_Tp, _ValT> || is_integral_v<_Tp>);
681#endif
682
683 //
684 // Move iterator type
685 //
686 template<typename _Tp>
687 struct __is_move_iterator
688 {
689 enum { __value = 0 };
690 typedef __false_type __type;
691 };
692
693 // Fallback implementation of the function in bits/stl_iterator.h used to
694 // remove the move_iterator wrapper.
695 template<typename _Iterator>
696 _GLIBCXX20_CONSTEXPR
697 inline _Iterator
698 __miter_base(_Iterator __it)
699 { return __it; }
700
701_GLIBCXX_END_NAMESPACE_VERSION
702} // namespace
703} // extern "C++"
704
705#pragma GCC diagnostic pop
706
707#endif //_CPP_TYPE_TRAITS_H
ISO C++ entities toplevel namespace is std.
GNU extensions for public use.