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