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