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