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