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}
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#pragma GCC system_header
36
37#include <bits/c++config.h>
38#include <bits/version.h>
39#if __glibcxx_type_trait_variable_templates
40# include <type_traits> // is_same_v, is_integral_v
41#endif
42
43//
44// This file provides some compile-time information about various types.
45// These representations were designed, on purpose, to be constant-expressions
46// and not types as found in <bits/type_traits.h>. In particular, they
47// can be used in control structures and the optimizer hopefully will do
48// the obvious thing.
49//
50// Why integral expressions, and not functions nor types?
51// Firstly, these compile-time entities are used as template-arguments
52// so function return values won't work: We need compile-time entities.
53// We're left with types and constant integral expressions.
54// Secondly, from the point of view of ease of use, type-based compile-time
55// information is -not- *that* convenient. One has to write lots of
56// overloaded functions and to hope that the compiler will select the right
57// one. As a net effect, the overall structure isn't very clear at first
58// glance.
59// Thirdly, partial ordering and overload resolution (of function templates)
60// is highly costly in terms of compiler-resource. It is a Good Thing to
61// keep these resource consumption as least as possible.
62//
63// See valarray_array.h for a case use.
64//
65// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06.
66//
67// Update 2005: types are also provided and <bits/type_traits.h> has been
68// removed.
69//
70
71extern "C++" {
72
73namespace std _GLIBCXX_VISIBILITY(default)
74{
75_GLIBCXX_BEGIN_NAMESPACE_VERSION
76
77 struct __true_type { };
78 struct __false_type { };
79
80 template<bool>
81 struct __truth_type
82 { typedef __false_type __type; };
83
84 template<>
85 struct __truth_type<true>
86 { typedef __true_type __type; };
87
88 // N.B. The conversions to bool are needed due to the issue
89 // explained in c++/19404.
90 template<class _Sp, class _Tp>
91 struct __traitor
92 {
93 enum { __value = bool(_Sp::__value) || bool(_Tp::__value) };
94 typedef typename __truth_type<__value>::__type __type;
95 };
96
97 // Compare for equality of types.
98 template<typename, typename>
99 struct __are_same
100 {
101 enum { __value = 0 };
102 typedef __false_type __type;
103 };
104
105 template<typename _Tp>
106 struct __are_same<_Tp, _Tp>
107 {
108 enum { __value = 1 };
109 typedef __true_type __type;
110 };
111
112 //
113 // Integer types
114 //
115 template<typename _Tp>
116 struct __is_integer
117 {
118 enum { __value = 0 };
119 typedef __false_type __type;
120 };
121
122 // Explicit specializations for the standard integer types.
123 // Up to four target-specific __int<N> types are supported as well.
124 template<>
125 struct __is_integer<bool>
126 {
127 enum { __value = 1 };
128 typedef __true_type __type;
129 };
130
131 template<>
132 struct __is_integer<char>
133 {
134 enum { __value = 1 };
135 typedef __true_type __type;
136 };
137
138 template<>
139 struct __is_integer<signed char>
140 {
141 enum { __value = 1 };
142 typedef __true_type __type;
143 };
144
145 template<>
146 struct __is_integer<unsigned char>
147 {
148 enum { __value = 1 };
149 typedef __true_type __type;
150 };
151
152# ifdef __WCHAR_TYPE__
153 template<>
154 struct __is_integer<wchar_t>
155 {
156 enum { __value = 1 };
157 typedef __true_type __type;
158 };
159# endif
160
161#ifdef _GLIBCXX_USE_CHAR8_T
162 template<>
163 struct __is_integer<char8_t>
164 {
165 enum { __value = 1 };
166 typedef __true_type __type;
167 };
168#endif
169
170#if __cplusplus >= 201103L
171 template<>
172 struct __is_integer<char16_t>
173 {
174 enum { __value = 1 };
175 typedef __true_type __type;
176 };
177
178 template<>
179 struct __is_integer<char32_t>
180 {
181 enum { __value = 1 };
182 typedef __true_type __type;
183 };
184#endif
185
186 template<>
187 struct __is_integer<short>
188 {
189 enum { __value = 1 };
190 typedef __true_type __type;
191 };
192
193 template<>
194 struct __is_integer<unsigned short>
195 {
196 enum { __value = 1 };
197 typedef __true_type __type;
198 };
199
200 template<>
201 struct __is_integer<int>
202 {
203 enum { __value = 1 };
204 typedef __true_type __type;
205 };
206
207 template<>
208 struct __is_integer<unsigned int>
209 {
210 enum { __value = 1 };
211 typedef __true_type __type;
212 };
213
214 template<>
215 struct __is_integer<long>
216 {
217 enum { __value = 1 };
218 typedef __true_type __type;
219 };
220
221 template<>
222 struct __is_integer<unsigned long>
223 {
224 enum { __value = 1 };
225 typedef __true_type __type;
226 };
227
228 template<>
229 struct __is_integer<long long>
230 {
231 enum { __value = 1 };
232 typedef __true_type __type;
233 };
234
235 template<>
236 struct __is_integer<unsigned long long>
237 {
238 enum { __value = 1 };
239 typedef __true_type __type;
240 };
241
242#define __INT_N(TYPE) \
243 __extension__ \
244 template<> \
245 struct __is_integer<TYPE> \
246 { \
247 enum { __value = 1 }; \
248 typedef __true_type __type; \
249 }; \
250 __extension__ \
251 template<> \
252 struct __is_integer<unsigned TYPE> \
253 { \
254 enum { __value = 1 }; \
255 typedef __true_type __type; \
256 };
257
258#ifdef __GLIBCXX_TYPE_INT_N_0
259__INT_N(__GLIBCXX_TYPE_INT_N_0)
260#endif
261#ifdef __GLIBCXX_TYPE_INT_N_1
262__INT_N(__GLIBCXX_TYPE_INT_N_1)
263#endif
264#ifdef __GLIBCXX_TYPE_INT_N_2
265__INT_N(__GLIBCXX_TYPE_INT_N_2)
266#endif
267#ifdef __GLIBCXX_TYPE_INT_N_3
268__INT_N(__GLIBCXX_TYPE_INT_N_3)
269#endif
270
271#undef __INT_N
272
273 //
274 // Floating point types
275 //
276 template<typename _Tp>
277 struct __is_floating
278 {
279 enum { __value = 0 };
280 typedef __false_type __type;
281 };
282
283 // three specializations (float, double and 'long double')
284 template<>
285 struct __is_floating<float>
286 {
287 enum { __value = 1 };
288 typedef __true_type __type;
289 };
290
291 template<>
292 struct __is_floating<double>
293 {
294 enum { __value = 1 };
295 typedef __true_type __type;
296 };
297
298 template<>
299 struct __is_floating<long double>
300 {
301 enum { __value = 1 };
302 typedef __true_type __type;
303 };
304
305#ifdef __STDCPP_FLOAT16_T__
306 template<>
307 struct __is_floating<_Float16>
308 {
309 enum { __value = 1 };
310 typedef __true_type __type;
311 };
312#endif
313
314#ifdef __STDCPP_FLOAT32_T__
315 template<>
316 struct __is_floating<_Float32>
317 {
318 enum { __value = 1 };
319 typedef __true_type __type;
320 };
321#endif
322
323#ifdef __STDCPP_FLOAT64_T__
324 template<>
325 struct __is_floating<_Float64>
326 {
327 enum { __value = 1 };
328 typedef __true_type __type;
329 };
330#endif
331
332#ifdef __STDCPP_FLOAT128_T__
333 template<>
334 struct __is_floating<_Float128>
335 {
336 enum { __value = 1 };
337 typedef __true_type __type;
338 };
339#endif
340
341#ifdef __STDCPP_BFLOAT16_T__
342 template<>
343 struct __is_floating<__gnu_cxx::__bfloat16_t>
344 {
345 enum { __value = 1 };
346 typedef __true_type __type;
347 };
348#endif
349
350 //
351 // An arithmetic type is an integer type or a floating point type
352 //
353 template<typename _Tp>
354 struct __is_arithmetic
355 : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> >
356 { };
357
358 //
359 // For use in std::copy and std::find overloads for streambuf iterators.
360 //
361 template<typename _Tp>
362 struct __is_char
363 {
364 enum { __value = 0 };
365 typedef __false_type __type;
366 };
367
368 template<>
369 struct __is_char<char>
370 {
371 enum { __value = 1 };
372 typedef __true_type __type;
373 };
374
375#ifdef __WCHAR_TYPE__
376 template<>
377 struct __is_char<wchar_t>
378 {
379 enum { __value = 1 };
380 typedef __true_type __type;
381 };
382#endif
383
384 template<typename _Tp>
385 struct __is_byte
386 {
387 enum { __value = 0 };
388 typedef __false_type __type;
389 };
390
391 template<>
392 struct __is_byte<char>
393 {
394 enum { __value = 1 };
395 typedef __true_type __type;
396 };
397
398 template<>
399 struct __is_byte<signed char>
400 {
401 enum { __value = 1 };
402 typedef __true_type __type;
403 };
404
405 template<>
406 struct __is_byte<unsigned char>
407 {
408 enum { __value = 1 };
409 typedef __true_type __type;
410 };
411
412#if __cplusplus >= 201703L
413 enum class byte : unsigned char;
414
415 template<>
416 struct __is_byte<byte>
417 {
418 enum { __value = 1 };
419 typedef __true_type __type;
420 };
421#endif // C++17
422
423#ifdef _GLIBCXX_USE_CHAR8_T
424 template<>
425 struct __is_byte<char8_t>
426 {
427 enum { __value = 1 };
428 typedef __true_type __type;
429 };
430#endif
431
432 template<typename> struct iterator_traits;
433
434 // A type that is safe for use with memcpy, memmove, memcmp etc.
435 template<typename _Tp>
436 struct __is_nonvolatile_trivially_copyable
437 {
438 enum { __value = __is_trivially_copyable(_Tp) };
439 };
440
441 // Cannot use memcpy/memmove/memcmp on volatile types even if they are
442 // trivially copyable, so ensure __memcpyable<volatile int*, volatile int*>
443 // and similar will be false.
444 template<typename _Tp>
445 struct __is_nonvolatile_trivially_copyable<volatile _Tp>
446 {
447 enum { __value = 0 };
448 };
449
450 // Whether two iterator types can be used with memcpy/memmove.
451 template<typename _OutputIter, typename _InputIter>
452 struct __memcpyable
453 {
454 enum { __value = 0 };
455 };
456
457 template<typename _Tp>
458 struct __memcpyable<_Tp*, _Tp*>
459 : __is_nonvolatile_trivially_copyable<_Tp>
460 { };
461
462 template<typename _Tp>
463 struct __memcpyable<_Tp*, const _Tp*>
464 : __is_nonvolatile_trivially_copyable<_Tp>
465 { };
466
467 // Whether two iterator types can be used with memcmp.
468 // This trait only says it's well-formed to use memcmp, not that it
469 // gives the right answer for a given algorithm. So for example, std::equal
470 // needs to add additional checks that the types are integers or pointers,
471 // because other trivially copyable types can overload operator==.
472 template<typename _Iter1, typename _Iter2>
473 struct __memcmpable
474 {
475 enum { __value = 0 };
476 };
477
478 // OK to use memcmp with pointers to trivially copyable types.
479 template<typename _Tp>
480 struct __memcmpable<_Tp*, _Tp*>
481 : __is_nonvolatile_trivially_copyable<_Tp>
482 { };
483
484 template<typename _Tp>
485 struct __memcmpable<const _Tp*, _Tp*>
486 : __is_nonvolatile_trivially_copyable<_Tp>
487 { };
488
489 template<typename _Tp>
490 struct __memcmpable<_Tp*, const _Tp*>
491 : __is_nonvolatile_trivially_copyable<_Tp>
492 { };
493
494 // Whether memcmp can be used to determine ordering for a type
495 // e.g. in std::lexicographical_compare or three-way comparisons.
496 // True for unsigned integer-like types where comparing each byte in turn
497 // as an unsigned char yields the right result. This is true for all
498 // unsigned integers on big endian targets, but only unsigned narrow
499 // character types (and std::byte) on little endian targets.
500 template<typename _Tp, bool _TreatAsBytes =
501#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
502 __is_integer<_Tp>::__value
503#else
504 __is_byte<_Tp>::__value
505#endif
506 >
507 struct __is_memcmp_ordered
508 {
509 static const bool __value = _Tp(-1) > _Tp(1); // is unsigned
510 };
511
512 template<typename _Tp>
513 struct __is_memcmp_ordered<_Tp, false>
514 {
515 static const bool __value = false;
516 };
517
518 // Whether two types can be compared using memcmp.
519 template<typename _Tp, typename _Up, bool = sizeof(_Tp) == sizeof(_Up)>
520 struct __is_memcmp_ordered_with
521 {
522 static const bool __value = __is_memcmp_ordered<_Tp>::__value
523 && __is_memcmp_ordered<_Up>::__value;
524 };
525
526 template<typename _Tp, typename _Up>
527 struct __is_memcmp_ordered_with<_Tp, _Up, false>
528 {
529 static const bool __value = false;
530 };
531
532#if __cplusplus >= 201703L
533#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
534 // std::byte is not an integer, but it can be compared using memcmp.
535 template<>
536 struct __is_memcmp_ordered<std::byte, false>
537 { static constexpr bool __value = true; };
538#endif
539
540 // std::byte can only be compared to itself, not to other types.
541 template<>
542 struct __is_memcmp_ordered_with<std::byte, std::byte, true>
543 { static constexpr bool __value = true; };
544
545 template<typename _Tp, bool _SameSize>
546 struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize>
547 { static constexpr bool __value = false; };
548
549 template<typename _Up, bool _SameSize>
550 struct __is_memcmp_ordered_with<std::byte, _Up, _SameSize>
551 { static constexpr bool __value = false; };
552#endif
553
554#if __glibcxx_type_trait_variable_templates
555 template<typename _ValT, typename _Tp>
556 constexpr bool __can_use_memchr_for_find
557 // Can only use memchr to search for narrow characters and std::byte.
558 = __is_byte<_ValT>::__value
559 // And only if the value to find is an integer (or is also std::byte).
560 && (is_same_v<_Tp, _ValT> || is_integral_v<_Tp>);
561#endif
562
563 //
564 // Move iterator type
565 //
566 template<typename _Tp>
567 struct __is_move_iterator
568 {
569 enum { __value = 0 };
570 typedef __false_type __type;
571 };
572
573 // Fallback implementation of the function in bits/stl_iterator.h used to
574 // remove the move_iterator wrapper.
575 template<typename _Iterator>
576 _GLIBCXX20_CONSTEXPR
577 inline _Iterator
578 __miter_base(_Iterator __it)
579 { return __it; }
580
581_GLIBCXX_END_NAMESPACE_VERSION
582} // namespace
583} // extern "C++"
584
585#endif //_CPP_TYPE_TRAITS_H
ISO C++ entities toplevel namespace is std.
GNU extensions for public use.