1// -*- C++ -*- Time-stamp: <08/07/20 19:10:15 ptr>
2
3/*
4 * Copyright (c) 2007, 2008
5 * Petr Ovtchenkov
6 *
7 * Licensed under the Academic Free License version 3.0
8 *
9 * Derived from original <misc/type_traits.h> of 'complement' project
10 * [http://complement.sourceforge.net]
11 * to make it close to JTC1/SC22/WG21 C++ 0x working draft
12 * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf]
13 */
14
15#ifndef __STLP_TYPE_TRAITS
16#define __STLP_TYPE_TRAITS
17
18#ifndef _STLP_OUTERMOST_HEADER_ID
19#  define _STLP_OUTERMOST_HEADER_ID 0x3
20#  include <stl/_prolog.h>
21#endif
22
23#include <stl/_cstddef.h> // for std::size_t
24
25// libstdc++ v3, timestamp 20050519 (3.4.4) has __type_traits,
26// libstdc++ v3, timestamp 20060306 (3.4.6) has __type_traits,
27// while libstdc++ v3, 20050921 (4.0.2) not; use libstdc++ instead
28// # if defined(STLPORT) || (defined(__GNUC__) && (__GNUC__ < 4)) /* !defined(__GLIBCXX__) || (defined(__GNUC__) && (__GNUC__ < 4)) */
29
30_STLP_BEGIN_NAMESPACE
31
32_STLP_BEGIN_TR1_NAMESPACE
33
34namespace detail {
35
36struct __select_types
37{
38    typedef char __t1;
39    struct __t2
40    {
41        char __two[2];
42    };
43};
44
45template <class _Tp>
46struct __instance :
47    public __select_types
48{
49  private:
50    template <class _Up>
51    static __t1 __test(_Up(*)[1]);
52
53    template <class>
54    static __t2 __test(...);
55    
56  public:
57#ifdef _STLP_STATIC_CONST_INIT_BUG
58    static const bool __value;
59#else
60    static const bool __value = sizeof(__test<_Tp>(0)) == sizeof(__select_types::__t1);
61#endif
62
63};
64
65#ifdef _STLP_STATIC_CONST_INIT_BUG
66template <class _Tp>
67const bool __instance<_Tp>::__value = sizeof(__instance<_Tp>::__test<_Tp>(0)) == sizeof(__select_types::__t1);
68#endif
69
70template <class T>
71struct __uoc_aux : // union or class
72    public __select_types
73{
74  private:
75    template <class _Up>
76    static __t1 __test( int _Up::* );
77
78    template <class>
79    static __t2 __test(...);
80    
81  public:
82#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION
83    static const bool __value;
84#else
85    static const bool __value = sizeof(__test<T>(0)) == sizeof(__select_types::__t1);
86#endif
87};
88
89#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION
90template <class T>
91const bool __uoc_aux<T>::__value = sizeof(__uoc_aux<T>::__test<T>(0)) == sizeof(__select_types::__t1);
92#endif
93
94template <class T>
95class __empty
96{ };
97
98template <class T, bool B>
99class __inheritance_aux
100{};
101
102template <class T>
103class __inheritance_aux<T,true> :
104    public T
105{
106  public:
107    virtual ~__inheritance_aux()
108      { }
109};
110
111#if 0
112template <class T, bool B>
113struct __virtual_aux
114{
115  public:
116#ifdef _STLP_STATIC_CONST_INIT_BUG
117    static const bool __value;
118#else
119    static const bool __value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false;
120#endif
121};
122
123#ifdef _STLP_STATIC_CONST_INIT_BUG
124template <class T, bool B>
125const bool __virtual_aux<T,B>::__value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false;
126#endif
127#endif
128
129} // namespace detail
130
131template <class _Tp, _Tp __v>
132struct integral_constant
133{
134    static const _Tp                    value = __v;
135    // enum { value = __v }; ?
136
137    typedef _Tp                         value_type;
138    typedef integral_constant<_Tp, __v> type;
139};
140
141typedef integral_constant<bool, true>   true_type;
142typedef integral_constant<bool, false>  false_type;
143
144namespace detail {
145
146template <typename _Tp>
147struct __is_union_or_class :
148    public integral_constant<bool, __uoc_aux<_Tp>::__value>
149{ };
150
151#if 0
152template<typename _Tp>
153struct __is_vtbl : // has virtual table?
154    public integral_constant<bool, __virtual_aux<_Tp,__is_union_or_class<_Tp>::value >::__value>
155{ };
156#endif
157
158template <typename _Tp>
159struct __is_vtbl : // has virtual table?
160    public integral_constant<bool, __is_union_or_class<_Tp>::value ? (sizeof(__inheritance_aux<_Tp,__is_union_or_class<_Tp>::value>) == sizeof(_Tp)) : false >
161{ };
162
163} // namespace detail
164
165#define  __SPEC_(C,T,B)               \
166template <>                           \
167struct C<T> :                         \
168    public integral_constant<bool, B> \
169{ }
170
171#define __CV_SPEC(C,T,B) \
172__SPEC_(C,T,B);            \
173__SPEC_(C,const T,B);      \
174__SPEC_(C,volatile T,B);   \
175__SPEC_(C,const volatile T,B)
176
177#define  __SPEC_1(C,T,B)              \
178template <class _Tp>                  \
179struct C<T> :                         \
180    public integral_constant<bool, B> \
181{ }
182
183#define __CV_SPEC_1(C,T,B) \
184__SPEC_1(C,T,B);            \
185__SPEC_1(C,T const,B);      \
186__SPEC_1(C,T volatile,B);   \
187__SPEC_1(C,T const volatile,B)
188
189#define  __SPEC_2(C,T,B)              \
190template <class _Tp1, class _Tp2>     \
191struct C<T> :                         \
192    public integral_constant<bool, B> \
193{ }
194
195#define __CV_SPEC_2(C,T,B) \
196__SPEC_2(C,T,B);            \
197__SPEC_2(C,T const,B);      \
198__SPEC_2(C,T volatile,B);   \
199__SPEC_2(C,T const volatile,B)
200
201// [4.5.1] primary type categories:
202
203template <class _Tp>
204struct is_void :
205    public false_type
206{ };
207
208template <>
209struct is_void<void> :
210    public true_type
211{ };
212
213template <class _Tp>
214struct is_integral :
215    public false_type
216{ };
217
218__CV_SPEC(is_integral,bool,true);
219__CV_SPEC(is_integral,char,true);
220__CV_SPEC(is_integral,signed char,true);
221__CV_SPEC(is_integral,unsigned char,true);
222__CV_SPEC(is_integral,wchar_t,true);
223__CV_SPEC(is_integral,short,true);
224__CV_SPEC(is_integral,unsigned short,true);
225__CV_SPEC(is_integral,int,true);
226__CV_SPEC(is_integral,unsigned int,true);
227__CV_SPEC(is_integral,long,true);
228__CV_SPEC(is_integral,unsigned long,true);
229__CV_SPEC(is_integral,long long,true);
230__CV_SPEC(is_integral,unsigned long long,true);
231
232template <class _Tp>
233struct is_floating_point :
234    public false_type
235{ };
236
237__CV_SPEC(is_floating_point,float,true);
238__CV_SPEC(is_floating_point,double,true);
239__CV_SPEC(is_floating_point,long double,true);
240
241template <class _Tp>
242struct is_array :
243    public false_type
244{ };
245
246template <class _Tp, std::size_t _Sz>
247struct is_array<_Tp[_Sz]> :
248    public true_type
249{ };
250
251template <class _Tp>
252struct is_array<_Tp[]> :
253    public true_type
254{ };
255
256template <class _Tp>
257struct is_pointer :
258    public false_type
259{ };
260
261__CV_SPEC_1(is_pointer,_Tp *,true);
262
263template <class _Tp>
264struct is_lvalue_reference :
265    public false_type
266{ };
267
268template <class _Tp>
269struct is_lvalue_reference<_Tp&> :
270    public true_type
271{ };
272
273template <class _Tp>
274struct is_rvalue_reference :
275    public false_type
276{ };
277
278// template <class _Tp>
279// struct is_rvalue_reference<_Tp&&> :
280//     public true_type
281// { };
282
283template <class _Tp>
284struct is_reference :
285    public false_type
286{ };
287
288template <class _Tp>
289struct is_reference<_Tp&> :
290    public true_type
291{ };
292
293template <class _Tp>
294struct is_function :
295    public integral_constant<bool, !(detail::__instance<_Tp>::__value
296                                     || detail::__is_union_or_class<_Tp>::value
297                                     || is_reference<_Tp>::value
298                                     || is_void<_Tp>::value)>
299{ };
300
301template <class _Tp>
302struct is_member_object_pointer :
303    public false_type
304{ };
305
306// _SPEC_FULL2(is_member_object_pointer, _Tp1 _Tp2::*,!is_function<_Tp1>::value);
307
308template <class _Tp1, class _Tp2>
309struct is_member_object_pointer<_Tp1 _Tp2::*> :
310    public integral_constant<bool, !is_function<_Tp1>::value>
311{ };
312
313template <class _Tp1, class _Tp2>
314struct is_member_object_pointer<_Tp1 _Tp2::* const> :
315    public integral_constant<bool, !is_function<_Tp1>::value>
316{ };
317
318template <class _Tp1, class _Tp2>
319struct is_member_object_pointer<_Tp1 _Tp2::* volatile> :
320    public integral_constant<bool, !is_function<_Tp1>::value>
321{ };
322
323template <class _Tp1, class _Tp2>
324struct is_member_object_pointer<_Tp1 _Tp2::* const volatile> :
325    public integral_constant<bool, !is_function<_Tp1>::value>
326{ };
327
328template <class _Tp>
329struct is_member_function_pointer :
330    public false_type
331{ };
332
333// _SPEC_FULL2(is_member_function_pointer,_Tp1 _Tp2::*,is_function<_Tp1>::value);
334
335template <class _Tp1, class _Tp2>
336struct is_member_function_pointer<_Tp1 _Tp2::*> :                         
337    public integral_constant<bool, is_function<_Tp1>::value> 
338{ };
339
340template <class _Tp1, class _Tp2>
341struct is_member_function_pointer<_Tp1 _Tp2::* const> :
342    public integral_constant<bool, is_function<_Tp1>::value>
343{ };
344
345template <class _Tp1, class _Tp2>
346struct is_member_function_pointer<_Tp1 _Tp2::* volatile> :
347    public integral_constant<bool, is_function<_Tp1>::value>
348{ };
349
350template <class _Tp1, class _Tp2>
351struct is_member_function_pointer<_Tp1 _Tp2::* const volatile> :
352    public integral_constant<bool, is_function<_Tp1>::value>
353{ };
354
355template <class _Tp>
356struct is_member_pointer :
357    public integral_constant<bool, (is_member_object_pointer<_Tp>::value || is_member_function_pointer<_Tp>::value)>
358{ };
359
360// 4.5.2 composite type categories
361
362template <class _Tp>
363struct is_arithmetic :
364    public integral_constant<bool, (is_integral<_Tp>::value || is_floating_point<_Tp>::value)>
365{ };
366
367template <class _Tp>
368struct is_fundamental :
369    public integral_constant<bool, (is_arithmetic<_Tp>::value || is_void<_Tp>::value)>
370{ };
371
372// [4.5.1] primary type categories (continued):
373
374template <class _Tp>
375struct is_enum :
376    public integral_constant<bool, !(is_fundamental<_Tp>::value
377                                     || is_array<_Tp>::value
378                                     || is_pointer<_Tp>::value
379                                     || is_reference<_Tp>::value
380                                     || is_member_pointer<_Tp>::value
381                                     || is_function<_Tp>::value
382                                     || detail::__is_union_or_class<_Tp>::value) >
383{ };
384
385template <class T>
386struct is_union
387{ };
388
389template <class T>
390struct is_class
391{ };
392
393// is_function (above)
394
395// 4.5.2 composite type categories (continued)
396
397// is_arithmetic (above)
398// is_fundamental (above)
399
400template <class _Tp>
401struct is_object :
402    public integral_constant<bool, (is_arithmetic<_Tp>::value ||
403                                    is_array<_Tp>::value ||
404                                    is_pointer<_Tp>::value ||
405                                    is_member_pointer<_Tp>::value ||
406                                    detail::__is_union_or_class<_Tp>::value)>
407{ };
408
409template <class _Tp>
410struct is_scalar :
411    public integral_constant<bool, (is_arithmetic<_Tp>::value
412                                    || is_enum<_Tp>::value
413                                    || is_pointer<_Tp>::value
414                                    || is_member_pointer<_Tp>::value)>
415{ };
416
417template <class _Tp>
418struct is_compound :
419    public integral_constant<bool, !is_fundamental<_Tp>::value>
420{ };
421
422// is_member_pointer
423
424// 4.5.3 type properties:
425
426template <class _Tp>
427struct is_const :
428    public false_type
429{ };
430
431template <class _Tp>
432struct is_const<_Tp const> :
433    public true_type
434{ };
435
436template <class _Tp>
437struct is_volatile :
438    public false_type
439{ };
440
441template <class _Tp>
442struct is_volatile<_Tp volatile> :
443    public true_type
444{ };
445
446
447// 4.7.3 array modifications:
448
449template <class _Tp>
450struct remove_extent
451{
452    typedef _Tp type;
453};
454
455template <class _Tp, std::size_t _Sz>
456struct remove_extent<_Tp[_Sz]>
457{
458    typedef _Tp type;
459};
460
461template <class _Tp>
462struct remove_extent<_Tp[]>
463{
464    typedef _Tp type;
465};
466
467template <class _Tp>
468struct remove_all_extents
469{
470    typedef _Tp type;
471};
472
473template <class _Tp, std::size_t _Size>
474struct remove_all_extents<_Tp[_Size]>
475{
476    typedef typename remove_all_extents<_Tp>::type type;
477};
478
479template<typename _Tp>
480struct remove_all_extents<_Tp[]>
481{
482    typedef typename remove_all_extents<_Tp>::type type;
483};
484
485// 4.5.3 type properties (continued):
486
487template <class _Tp>
488struct is_trivial :
489    public integral_constant<bool, (is_void<_Tp>::value
490                                    || is_scalar<typename remove_all_extents<_Tp>::type>::value)>
491{ };
492
493template <class _Tp>
494struct is_standard_layout :
495    public integral_constant<bool, (is_void<_Tp>::value
496                                    || is_scalar<typename remove_all_extents<_Tp>::type>::value)>
497{ };
498
499template <class _Tp>
500struct is_pod :
501    public integral_constant<bool, (is_void<_Tp>::value
502                                    || is_scalar<typename remove_all_extents<_Tp>::type>::value)>
503{ };
504
505template<typename _Tp>
506struct is_empty
507    : public integral_constant<bool, (detail::__is_union_or_class<_Tp>::value
508                                      && (sizeof(detail::__empty<_Tp>) == sizeof(_Tp)))>
509{ };
510
511// is_polimorphic
512// is_abstract
513
514template <class _Tp>
515struct has_trivial_constructor :
516    public integral_constant<bool, is_pod<_Tp>::value>
517{ };
518
519template <class _Tp>
520struct has_trivial_copy :
521    public integral_constant<bool, is_pod<_Tp>::value>
522{ };
523
524template <class _Tp>
525struct has_trivial_assign :
526    public integral_constant<bool, is_pod<_Tp>::value>
527{ };
528
529template <class _Tp>
530struct has_trivial_destructor :
531    public integral_constant<bool, is_pod<_Tp>::value>
532{ };
533
534template <class _Tp>
535struct has_nothrow_constructor :
536    public integral_constant<bool, is_pod<_Tp>::value>
537{ };
538
539template <class _Tp>
540struct has_nothrow_copy :
541    public integral_constant<bool, is_pod<_Tp>::value>
542{ };
543
544template <class _Tp>
545struct has_nothrow_assign :
546    public integral_constant<bool, is_pod<_Tp>::value>
547{ };
548
549template <class _Tp>
550struct has_virtual_destructor :
551    public false_type
552{ };
553
554template <class _Tp>
555struct is_signed :
556    public false_type
557{ };
558
559__CV_SPEC(is_signed,signed char,true);
560__CV_SPEC(is_signed,short,true);
561__CV_SPEC(is_signed,int,true);
562__CV_SPEC(is_signed,long,true);
563__CV_SPEC(is_signed,long long,true);
564
565template <class _Tp>
566struct is_unsigned :
567    public false_type
568{ };
569
570__CV_SPEC(is_unsigned,unsigned char,true);
571__CV_SPEC(is_unsigned,unsigned short,true);
572__CV_SPEC(is_unsigned,unsigned int,true);
573__CV_SPEC(is_unsigned,unsigned long,true);
574__CV_SPEC(is_unsigned,unsigned long long,true);
575
576// alignment_of
577// rank
578// extent
579
580// 4.6 type relations:
581
582template <class _Tp1, class _Tp2>
583struct is_same :
584    public false_type
585{ };
586
587template <class _Tp>
588struct is_same<_Tp, _Tp> :
589    public true_type
590{ };
591
592// is_base_of
593// is_convertible
594
595// 4.7.1 const-volatile modifications
596
597template <class _Tp>
598struct remove_const
599{
600    typedef _Tp type;
601};
602
603template <class _Tp>
604struct remove_const<_Tp const>
605{
606    typedef _Tp type;
607};
608  
609template <class _Tp>
610struct remove_volatile
611{
612    typedef _Tp type;
613};
614
615template <class _Tp>
616struct remove_volatile<_Tp volatile>
617{
618    typedef _Tp type;
619};
620
621template <class _Tp>
622struct remove_cv
623{
624    typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type;
625};
626  
627template <class _Tp>
628struct add_const
629{
630    typedef _Tp const type;
631};
632   
633template <class _Tp>
634struct add_volatile
635{
636    typedef _Tp volatile type;
637};
638  
639template <class _Tp>
640struct add_cv
641{
642    typedef typename add_const<typename add_volatile<_Tp>::type>::type type;
643};
644
645// 4.7.2 reference modifications:
646
647template <class _Tp>
648struct remove_reference
649{
650    typedef _Tp type;
651};
652
653template <class _Tp>
654struct remove_reference<_Tp&>
655{
656    typedef _Tp type;
657};
658
659#if __cplusplus >= 201103L
660// This shouldn't be in tr1 but was added here anyways since the existing remove_reference is in
661// tr1.
662template <class _Tp>
663struct remove_reference<_Tp&&>
664{
665    typedef _Tp type;
666};
667#endif
668
669template <class _Tp>
670struct add_reference
671{
672    typedef _Tp& type;
673};
674
675template <class _Tp>
676struct add_reference<_Tp&>
677{
678    typedef _Tp& type;
679};
680
681// 4.7.3 array modifications (see above)
682
683// 4.7.4 pointer modifications:
684
685template <class _Tp>
686struct remove_pointer
687{
688    typedef _Tp type;
689};
690
691template <class _Tp>
692struct remove_pointer<_Tp *>
693{
694    typedef _Tp type;
695};
696
697template <class _Tp>
698struct remove_pointer<_Tp * const>
699{
700    typedef _Tp type;
701};
702
703template <class _Tp>
704struct remove_pointer<_Tp * volatile>
705{
706    typedef _Tp type;
707};
708
709template <class _Tp>
710struct remove_pointer<_Tp * const volatile>
711{
712    typedef _Tp type;
713};
714
715template <class _Tp>
716struct add_pointer
717{
718    typedef typename remove_reference<_Tp>::type * type;
719};
720
721// 20.5.7 other transformations:
722
723// template <std::size_t Len, std::size_t Align> struct aligned_storage;
724// template <std::size_t Len, class... Types> struct aligned_union;
725
726namespace detail {
727
728template <bool,class _U>
729struct _decay_aux2
730{
731    typedef typename remove_cv<_U>::type type;
732};
733
734template <class _U>
735struct _decay_aux2<true,_U>
736{
737    typedef typename add_pointer<_U>::type type;
738};
739
740template <bool, class _U>
741struct _decay_aux1
742{
743    typedef typename _decay_aux2<is_function<_U>::value,_U>::type type; 
744};
745
746template <class _U>
747struct _decay_aux1<true,_U>
748{
749    typedef typename remove_extent<_U>::type* type;
750};
751
752} // namespace detail
753
754template <class _Tp>
755class decay
756{
757  private:
758    typedef typename remove_reference<_Tp>::type _U;
759
760  public:
761    typedef typename detail::_decay_aux1<is_array<_U>::value,_U>::type type;
762};
763
764template <bool, class _Tp = void>
765struct enable_if
766{
767};
768
769template <class _Tp>
770struct enable_if<true,_Tp>
771{
772    typedef _Tp type;
773};
774
775template <bool, class _Tp1, class _Tp2>
776struct conditional
777{
778    typedef _Tp2 type;
779};
780
781template <class _Tp1, class _Tp2>
782struct conditional<true,_Tp1,_Tp2>
783{
784    typedef _Tp1 type;
785};
786
787// template <class... _Tp> struct common_type;
788
789#undef __CV_SPEC
790#undef __SPEC_
791#undef __CV_SPEC_1
792#undef __SPEC_1
793#undef __CV_SPEC_2
794#undef __SPEC_2
795
796_STLP_END_NAMESPACE // tr1
797
798_STLP_END_NAMESPACE
799
800// # else // __GLIBCXX__ && (__GNUC__ >= 4) && !STLPORT
801// #  include <tr1/type_traits>
802// # endif
803
804#if (_STLP_OUTERMOST_HEADER_ID == 0x3)
805#  include <stl/_epilog.h>
806#  undef _STLP_OUTERMOST_HEADER_ID
807#endif
808
809#endif // __STLP_TYPE_TRAITS
810
811