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