1// TR1 type_traits -*- C++ -*-
2
3// Copyright (C) 2004-2018 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 tr1/type_traits
26 *  This is a TR1 C++ Library header.
27 */
28
29#ifndef _GLIBCXX_TR1_TYPE_TRAITS
30#define _GLIBCXX_TR1_TYPE_TRAITS 1
31
32#pragma GCC system_header
33
34#include <bits/c++config.h>
35
36namespace std _GLIBCXX_VISIBILITY(default)
37{
38_GLIBCXX_BEGIN_NAMESPACE_VERSION
39
40namespace tr1
41{
42  /**
43   * @addtogroup metaprogramming
44   * @{
45   */
46
47  struct __sfinae_types
48  {
49    typedef char __one;
50    typedef struct { char __arr[2]; } __two;
51  };
52
53#define _DEFINE_SPEC_0_HELPER                          \
54  template<>
55
56#define _DEFINE_SPEC_1_HELPER                          \
57  template<typename _Tp>
58
59#define _DEFINE_SPEC_2_HELPER                          \
60  template<typename _Tp, typename _Cp>
61
62#define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)    \
63  _DEFINE_SPEC_##_Order##_HELPER                       \
64    struct _Trait<_Type>                               \
65    : public integral_constant<bool, _Value> { };
66
67  // helper classes [4.3].
68
69  /// integral_constant
70  template<typename _Tp, _Tp __v>
71    struct integral_constant
72    {
73      static const _Tp                      value = __v;
74      typedef _Tp                           value_type;
75      typedef integral_constant<_Tp, __v>   type;
76    };
77
78  /// typedef for true_type
79  typedef integral_constant<bool, true>     true_type;
80
81  /// typedef for false_type
82  typedef integral_constant<bool, false>    false_type;
83
84  template<typename _Tp, _Tp __v>
85    const _Tp integral_constant<_Tp, __v>::value;
86
87  /// remove_cv
88  template<typename>
89    struct remove_cv;
90
91  template<typename>
92    struct __is_void_helper
93    : public false_type { };
94  _DEFINE_SPEC(0, __is_void_helper, void, true)
95
96  // primary type categories [4.5.1].
97
98  /// is_void
99  template<typename _Tp>
100    struct is_void
101    : public integral_constant<bool, (__is_void_helper<typename
102				      remove_cv<_Tp>::type>::value)>
103    { };
104
105  template<typename>
106    struct __is_integral_helper
107    : public false_type { };
108  _DEFINE_SPEC(0, __is_integral_helper, bool, true)
109  _DEFINE_SPEC(0, __is_integral_helper, char, true)
110  _DEFINE_SPEC(0, __is_integral_helper, signed char, true)
111  _DEFINE_SPEC(0, __is_integral_helper, unsigned char, true)
112#ifdef _GLIBCXX_USE_WCHAR_T
113  _DEFINE_SPEC(0, __is_integral_helper, wchar_t, true)
114#endif
115  _DEFINE_SPEC(0, __is_integral_helper, short, true)
116  _DEFINE_SPEC(0, __is_integral_helper, unsigned short, true)
117  _DEFINE_SPEC(0, __is_integral_helper, int, true)
118  _DEFINE_SPEC(0, __is_integral_helper, unsigned int, true)
119  _DEFINE_SPEC(0, __is_integral_helper, long, true)
120  _DEFINE_SPEC(0, __is_integral_helper, unsigned long, true)
121  _DEFINE_SPEC(0, __is_integral_helper, long long, true)
122  _DEFINE_SPEC(0, __is_integral_helper, unsigned long long, true)
123
124  /// is_integral
125  template<typename _Tp>
126    struct is_integral
127    : public integral_constant<bool, (__is_integral_helper<typename
128				      remove_cv<_Tp>::type>::value)>
129    { };
130
131  template<typename>
132    struct __is_floating_point_helper
133    : public false_type { };
134  _DEFINE_SPEC(0, __is_floating_point_helper, float, true)
135  _DEFINE_SPEC(0, __is_floating_point_helper, double, true)
136  _DEFINE_SPEC(0, __is_floating_point_helper, long double, true)
137
138  /// is_floating_point
139  template<typename _Tp>
140    struct is_floating_point
141    : public integral_constant<bool, (__is_floating_point_helper<typename
142				      remove_cv<_Tp>::type>::value)>
143    { };
144
145  /// is_array
146  template<typename>
147    struct is_array
148    : public false_type { };
149
150  template<typename _Tp, std::size_t _Size>
151    struct is_array<_Tp[_Size]>
152    : public true_type { };
153
154  template<typename _Tp>
155    struct is_array<_Tp[]>
156    : public true_type { };
157
158  template<typename>
159    struct __is_pointer_helper
160    : public false_type { };
161  _DEFINE_SPEC(1, __is_pointer_helper, _Tp*, true)
162
163  /// is_pointer
164  template<typename _Tp>
165    struct is_pointer
166    : public integral_constant<bool, (__is_pointer_helper<typename
167				      remove_cv<_Tp>::type>::value)>
168    { };
169
170  /// is_reference
171  template<typename _Tp>
172    struct is_reference;
173
174  /// is_function
175  template<typename _Tp>
176    struct is_function;
177
178  template<typename>
179    struct __is_member_object_pointer_helper
180    : public false_type { };
181  _DEFINE_SPEC(2, __is_member_object_pointer_helper, _Tp _Cp::*,
182	       !is_function<_Tp>::value)
183
184  /// is_member_object_pointer
185  template<typename _Tp>
186    struct is_member_object_pointer
187    : public integral_constant<bool, (__is_member_object_pointer_helper<
188				      typename remove_cv<_Tp>::type>::value)>
189    { };
190
191  template<typename>
192    struct __is_member_function_pointer_helper
193    : public false_type { };
194  _DEFINE_SPEC(2, __is_member_function_pointer_helper, _Tp _Cp::*,
195	       is_function<_Tp>::value)
196
197  /// is_member_function_pointer
198  template<typename _Tp>
199    struct is_member_function_pointer
200    : public integral_constant<bool, (__is_member_function_pointer_helper<
201				      typename remove_cv<_Tp>::type>::value)>
202    { };
203
204  /// is_enum
205  template<typename _Tp>
206    struct is_enum
207    : public integral_constant<bool, __is_enum(_Tp)>
208    { };
209
210  /// is_union
211  template<typename _Tp>
212    struct is_union
213    : public integral_constant<bool, __is_union(_Tp)>
214    { };
215
216  /// is_class
217  template<typename _Tp>
218    struct is_class
219    : public integral_constant<bool, __is_class(_Tp)>
220    { };
221
222  /// is_function
223  template<typename>
224    struct is_function
225    : public false_type { };
226  template<typename _Res, typename... _ArgTypes>
227    struct is_function<_Res(_ArgTypes...)>
228    : public true_type { };
229  template<typename _Res, typename... _ArgTypes>
230    struct is_function<_Res(_ArgTypes......)>
231    : public true_type { };
232  template<typename _Res, typename... _ArgTypes>
233    struct is_function<_Res(_ArgTypes...) const>
234    : public true_type { };
235  template<typename _Res, typename... _ArgTypes>
236    struct is_function<_Res(_ArgTypes......) const>
237    : public true_type { };
238  template<typename _Res, typename... _ArgTypes>
239    struct is_function<_Res(_ArgTypes...) volatile>
240    : public true_type { };
241  template<typename _Res, typename... _ArgTypes>
242    struct is_function<_Res(_ArgTypes......) volatile>
243    : public true_type { };
244  template<typename _Res, typename... _ArgTypes>
245    struct is_function<_Res(_ArgTypes...) const volatile>
246    : public true_type { };
247  template<typename _Res, typename... _ArgTypes>
248    struct is_function<_Res(_ArgTypes......) const volatile>
249    : public true_type { };
250
251  // composite type traits [4.5.2].
252
253  /// is_arithmetic
254  template<typename _Tp>
255    struct is_arithmetic
256    : public integral_constant<bool, (is_integral<_Tp>::value
257				      || is_floating_point<_Tp>::value)>
258    { };
259
260  /// is_fundamental
261  template<typename _Tp>
262    struct is_fundamental
263    : public integral_constant<bool, (is_arithmetic<_Tp>::value
264				      || is_void<_Tp>::value)>
265    { };
266
267  /// is_object
268  template<typename _Tp>
269    struct is_object
270    : public integral_constant<bool, !(is_function<_Tp>::value
271				       || is_reference<_Tp>::value
272				       || is_void<_Tp>::value)>
273    { };
274
275  /// is_member_pointer
276  template<typename _Tp>
277    struct is_member_pointer;
278
279  /// is_scalar
280  template<typename _Tp>
281    struct is_scalar
282    : public integral_constant<bool, (is_arithmetic<_Tp>::value
283				      || is_enum<_Tp>::value
284				      || is_pointer<_Tp>::value
285				      || is_member_pointer<_Tp>::value)>
286    { };
287
288  /// is_compound
289  template<typename _Tp>
290    struct is_compound
291    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
292
293  /// is_member_pointer
294  template<typename _Tp>
295    struct __is_member_pointer_helper
296    : public false_type { };
297  _DEFINE_SPEC(2, __is_member_pointer_helper, _Tp _Cp::*, true)
298
299  template<typename _Tp>
300  struct is_member_pointer
301    : public integral_constant<bool, (__is_member_pointer_helper<
302				      typename remove_cv<_Tp>::type>::value)>
303    { };
304
305  // type properties [4.5.3].
306  /// is_const
307  template<typename>
308    struct is_const
309    : public false_type { };
310
311  template<typename _Tp>
312    struct is_const<_Tp const>
313    : public true_type { };
314
315  /// is_volatile
316  template<typename>
317    struct is_volatile
318    : public false_type { };
319
320  template<typename _Tp>
321    struct is_volatile<_Tp volatile>
322    : public true_type { };
323
324  /// is_empty
325  template<typename _Tp>
326    struct is_empty
327    : public integral_constant<bool, __is_empty(_Tp)>
328    { };
329
330  /// is_polymorphic
331  template<typename _Tp>
332    struct is_polymorphic
333    : public integral_constant<bool, __is_polymorphic(_Tp)>
334    { };
335
336  /// is_abstract
337  template<typename _Tp>
338    struct is_abstract
339    : public integral_constant<bool, __is_abstract(_Tp)>
340    { };
341
342  /// has_virtual_destructor
343  template<typename _Tp>
344    struct has_virtual_destructor
345    : public integral_constant<bool, __has_virtual_destructor(_Tp)>
346    { };
347
348  /// alignment_of
349  template<typename _Tp>
350    struct alignment_of
351    : public integral_constant<std::size_t, __alignof__(_Tp)> { };
352
353  /// rank
354  template<typename>
355    struct rank
356    : public integral_constant<std::size_t, 0> { };
357
358  template<typename _Tp, std::size_t _Size>
359    struct rank<_Tp[_Size]>
360    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
361
362  template<typename _Tp>
363    struct rank<_Tp[]>
364    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
365
366  /// extent
367  template<typename, unsigned _Uint = 0>
368    struct extent
369    : public integral_constant<std::size_t, 0> { };
370
371  template<typename _Tp, unsigned _Uint, std::size_t _Size>
372    struct extent<_Tp[_Size], _Uint>
373    : public integral_constant<std::size_t,
374			       _Uint == 0 ? _Size : extent<_Tp,
375							   _Uint - 1>::value>
376    { };
377
378  template<typename _Tp, unsigned _Uint>
379    struct extent<_Tp[], _Uint>
380    : public integral_constant<std::size_t,
381			       _Uint == 0 ? 0 : extent<_Tp,
382						       _Uint - 1>::value>
383    { };
384
385  // relationships between types [4.6].
386
387  /// is_same
388  template<typename, typename>
389    struct is_same
390    : public false_type { };
391
392  template<typename _Tp>
393    struct is_same<_Tp, _Tp>
394    : public true_type { };
395
396  // const-volatile modifications [4.7.1].
397
398  /// remove_const
399  template<typename _Tp>
400    struct remove_const
401    { typedef _Tp     type; };
402
403  template<typename _Tp>
404    struct remove_const<_Tp const>
405    { typedef _Tp     type; };
406
407  /// remove_volatile
408  template<typename _Tp>
409    struct remove_volatile
410    { typedef _Tp     type; };
411
412  template<typename _Tp>
413    struct remove_volatile<_Tp volatile>
414    { typedef _Tp     type; };
415
416  /// remove_cv
417  template<typename _Tp>
418    struct remove_cv
419    {
420      typedef typename
421      remove_const<typename remove_volatile<_Tp>::type>::type     type;
422    };
423
424  /// add_const
425  template<typename _Tp>
426    struct add_const
427    { typedef _Tp const     type; };
428
429  /// add_volatile
430  template<typename _Tp>
431    struct add_volatile
432    { typedef _Tp volatile     type; };
433
434  /// add_cv
435  template<typename _Tp>
436    struct add_cv
437    {
438      typedef typename
439      add_const<typename add_volatile<_Tp>::type>::type     type;
440    };
441
442  // array modifications [4.7.3].
443
444  /// remove_extent
445  template<typename _Tp>
446    struct remove_extent
447    { typedef _Tp     type; };
448
449  template<typename _Tp, std::size_t _Size>
450    struct remove_extent<_Tp[_Size]>
451    { typedef _Tp     type; };
452
453  template<typename _Tp>
454    struct remove_extent<_Tp[]>
455    { typedef _Tp     type; };
456
457  /// remove_all_extents
458  template<typename _Tp>
459    struct remove_all_extents
460    { typedef _Tp     type; };
461
462  template<typename _Tp, std::size_t _Size>
463    struct remove_all_extents<_Tp[_Size]>
464    { typedef typename remove_all_extents<_Tp>::type     type; };
465
466  template<typename _Tp>
467    struct remove_all_extents<_Tp[]>
468    { typedef typename remove_all_extents<_Tp>::type     type; };
469
470  // pointer modifications [4.7.4].
471
472  template<typename _Tp, typename>
473    struct __remove_pointer_helper
474    { typedef _Tp     type; };
475
476  template<typename _Tp, typename _Up>
477    struct __remove_pointer_helper<_Tp, _Up*>
478    { typedef _Up     type; };
479
480  /// remove_pointer
481  template<typename _Tp>
482    struct remove_pointer
483    : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type>
484    { };
485
486  template<typename>
487    struct remove_reference;
488
489  /// add_pointer
490  template<typename _Tp>
491    struct add_pointer
492    { typedef typename remove_reference<_Tp>::type*     type; };
493
494  template<typename>
495    struct is_reference
496    : public false_type { };
497
498  template<typename _Tp>
499    struct is_reference<_Tp&>
500    : public true_type { };
501
502  template<typename _Tp>
503    struct is_pod
504    : public integral_constant<bool, __is_pod(_Tp) || is_void<_Tp>::value>
505    { };
506
507  template<typename _Tp>
508    struct has_trivial_constructor
509    : public integral_constant<bool, is_pod<_Tp>::value>
510    { };
511
512  template<typename _Tp>
513    struct has_trivial_copy
514    : public integral_constant<bool, is_pod<_Tp>::value>
515    { };
516
517  template<typename _Tp>
518    struct has_trivial_assign
519    : public integral_constant<bool, is_pod<_Tp>::value>
520    { };
521
522  template<typename _Tp>
523    struct has_trivial_destructor
524    : public integral_constant<bool, is_pod<_Tp>::value>
525    { };
526
527  template<typename _Tp>
528    struct has_nothrow_constructor
529    : public integral_constant<bool, is_pod<_Tp>::value>
530    { };
531
532  template<typename _Tp>
533    struct has_nothrow_copy
534    : public integral_constant<bool, is_pod<_Tp>::value>
535    { };
536
537  template<typename _Tp>
538    struct has_nothrow_assign
539    : public integral_constant<bool, is_pod<_Tp>::value>
540    { };
541
542  template<typename>
543    struct __is_signed_helper
544    : public false_type { };
545  _DEFINE_SPEC(0, __is_signed_helper, signed char, true)
546  _DEFINE_SPEC(0, __is_signed_helper, short, true)
547  _DEFINE_SPEC(0, __is_signed_helper, int, true)
548  _DEFINE_SPEC(0, __is_signed_helper, long, true)
549  _DEFINE_SPEC(0, __is_signed_helper, long long, true)
550
551  template<typename _Tp>
552    struct is_signed
553    : public integral_constant<bool, (__is_signed_helper<typename
554				      remove_cv<_Tp>::type>::value)>
555    { };
556
557  template<typename>
558    struct __is_unsigned_helper
559    : public false_type { };
560  _DEFINE_SPEC(0, __is_unsigned_helper, unsigned char, true)
561  _DEFINE_SPEC(0, __is_unsigned_helper, unsigned short, true)
562  _DEFINE_SPEC(0, __is_unsigned_helper, unsigned int, true)
563  _DEFINE_SPEC(0, __is_unsigned_helper, unsigned long, true)
564  _DEFINE_SPEC(0, __is_unsigned_helper, unsigned long long, true)
565
566  template<typename _Tp>
567    struct is_unsigned
568    : public integral_constant<bool, (__is_unsigned_helper<typename
569				      remove_cv<_Tp>::type>::value)>
570    { };
571
572  template<typename _Base, typename _Derived>
573    struct __is_base_of_helper
574    {
575      typedef typename remove_cv<_Base>::type    _NoCv_Base;
576      typedef typename remove_cv<_Derived>::type _NoCv_Derived;
577      static const bool __value = (is_same<_Base, _Derived>::value
578				   || (__is_base_of(_Base, _Derived)
579				       && !is_same<_NoCv_Base,
580				                   _NoCv_Derived>::value));
581    };
582
583  template<typename _Base, typename _Derived>
584    struct is_base_of
585    : public integral_constant<bool,
586			       __is_base_of_helper<_Base, _Derived>::__value>
587    { };
588
589  template<typename _From, typename _To>
590    struct __is_convertible_simple
591    : public __sfinae_types
592    {
593    private:
594      static __one __test(_To);
595      static __two __test(...);
596      static _From __makeFrom();
597
598    public:
599      static const bool __value = sizeof(__test(__makeFrom())) == 1;
600    };
601
602  template<typename _Tp>
603    struct add_reference;
604
605  template<typename _Tp>
606    struct __is_int_or_cref
607    {
608      typedef typename remove_reference<_Tp>::type __rr_Tp;
609      static const bool __value = (is_integral<_Tp>::value
610				   || (is_integral<__rr_Tp>::value
611				       && is_const<__rr_Tp>::value
612				       && !is_volatile<__rr_Tp>::value));
613    };
614
615  template<typename _From, typename _To,
616	   bool = (is_void<_From>::value || is_void<_To>::value
617		   || is_function<_To>::value || is_array<_To>::value
618		   // This special case is here only to avoid warnings.
619		   || (is_floating_point<typename
620		       remove_reference<_From>::type>::value
621		       && __is_int_or_cref<_To>::__value))>
622    struct __is_convertible_helper
623    {
624      // "An imaginary lvalue of type From...".
625      static const bool __value = (__is_convertible_simple<typename
626				   add_reference<_From>::type, _To>::__value);
627    };
628
629  template<typename _From, typename _To>
630    struct __is_convertible_helper<_From, _To, true>
631    { static const bool __value = (is_void<_To>::value
632				   || (__is_int_or_cref<_To>::__value
633				       && !is_void<_From>::value)); };
634
635  template<typename _From, typename _To>
636    struct is_convertible
637    : public integral_constant<bool,
638			       __is_convertible_helper<_From, _To>::__value>
639    { };
640
641  // reference modifications [4.7.2].
642  template<typename _Tp>
643    struct remove_reference
644    { typedef _Tp     type; };
645
646  template<typename _Tp>
647    struct remove_reference<_Tp&>
648    { typedef _Tp     type; };
649
650  // NB: Careful with reference to void.
651  template<typename _Tp, bool = (is_void<_Tp>::value
652				 || is_reference<_Tp>::value)>
653    struct __add_reference_helper
654    { typedef _Tp&    type; };
655
656  template<typename _Tp>
657    struct __add_reference_helper<_Tp, true>
658    { typedef _Tp     type; };
659
660  template<typename _Tp>
661    struct add_reference
662    : public __add_reference_helper<_Tp>
663    { };
664
665  // other transformations [4.8].
666  template<std::size_t _Len, std::size_t _Align>
667    struct aligned_storage
668    {
669      union type
670      {
671	unsigned char __data[_Len];
672	struct __attribute__((__aligned__((_Align)))) { } __align;
673      };
674    };
675
676#undef _DEFINE_SPEC_0_HELPER
677#undef _DEFINE_SPEC_1_HELPER
678#undef _DEFINE_SPEC_2_HELPER
679#undef _DEFINE_SPEC
680
681  /// @} group metaprogramming
682}
683
684_GLIBCXX_END_NAMESPACE_VERSION
685}
686
687#endif // _GLIBCXX_TR1_TYPE_TRAITS
688