1 /*
2  *  TypeTraits.h
3  *  Apto
4  *
5  *  Created by David on 5/12/11.
6  *  Copyright 2011 David Michael Bryson. All rights reserved.
7  *  http://programerror.com/software/apto
8  *
9  *  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
10  *  following conditions are met:
11  *
12  *  1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the
13  *      following disclaimer.
14  *  2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15  *      following disclaimer in the documentation and/or other materials provided with the distribution.
16  *  3.  Neither the name of David Michael Bryson, nor the names of contributors may be used to endorse or promote
17  *      products derived from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY DAVID MICHAEL BRYSON AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  *  DISCLAIMED. IN NO EVENT SHALL DAVID MICHAEL BRYSON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  *  Authors: David M. Bryson <david@programerror.com>
28  *
29  *  TypeTraits based off of ideas presented in Modern C++ Design (2001) by Andrei Alexandrescu
30  */
31 
32 #ifndef AptoCoreTypeTraits_h
33 #define AptoCoreTypeTraits_h
34 
35 #include "apto/core/TypeList.h"
36 
37 namespace Apto {
38 
39   namespace Types {
40     typedef TL::Create<
41       unsigned char, unsigned short int, unsigned int, unsigned long int, unsigned long long int
42     >::Type StandardUnsignedInts;
43 
44     typedef TL::Create<
45       signed char, signed short int, signed int, signed long int, signed long long int
46     >::Type StandardSignedInts;
47 
48     typedef TL::Create<
49       bool, char, wchar_t
50     >::Type StandardOtherInts;
51 
52     typedef TL::Create<
53       float, double, long double
54     >::Type StandardFloatingPoint;
55   }
56 
57   namespace Internal {
58     template <class U> struct MakeParameterType
59     {
60       typedef const U& Result;
61     };
62     template <class U> struct MakeParameterType<U&>
63     {
64       typedef U& Result;
65     };
66     template <> struct MakeParameterType<void>
67     {
68       typedef NullType Result;
69     };
70   }
71 
72   template <typename T> class TypeTraits
73   {
74   private:
75     template <class U> struct ReferenceTraits
76     {
77       enum { Result = false };
78       typedef U ReferredType;
79     };
80     template <class U> struct ReferenceTraits<U&>
81     {
82       enum { Result = true };
83       typedef U ReferredType;
84     };
85 
86 
87     template <class U> struct PointerTraits
88     {
89       enum { Result = false };
90       typedef NullType PointeeType;
91     };
92     template <class U> struct PointerTraits<U*>
93     {
94       enum { Result = true };
95       typedef U PointeeType;
96     };
97     template <class U> struct PointerTraits<U*&>
98     {
99       enum { Result = true };
100       typedef U PointeeType;
101     };
102 
103 
104     template <class U> struct PointerToMemberTraits
105     {
106       enum { Result = false };
107     };
108     template <class U, class V> struct PointerToMemberTraits<U V::*>
109     {
110       enum { Result = true };
111     };
112     template <class U, class V> struct PointerToMemberTraits<U V::*&>
113     {
114       enum { Result = true };
115     };
116 
117 
118     template <class U> struct UnConst
119     {
120       typedef U Result;
121       enum { IsConst = false };
122     };
123     template <class U> struct UnConst<const U>
124     {
125       typedef U Result;
126       enum { IsConst = true };
127     };
128     template <class U> struct UnConst<const U&>
129     {
130       typedef U Result;
131       enum { IsConst = true };
132     };
133 
134 
135     template <class U> struct UnVolatile
136     {
137       typedef U Result;
138       enum { IsVolatile = false };
139     };
140     template <class U> struct UnVolatile<const U>
141     {
142       typedef U Result;
143       enum { IsVolatile = true };
144     };
145     template <class U> struct UnVolatile<const U&>
146     {
147       typedef U Result;
148       enum { IsVolatile = true };
149     };
150 
151 
152   public:
153     typedef typename UnConst<T>::Result NonConstType;
154     typedef typename UnVolatile<T>::Result NonVolatileType;
155     typedef typename UnVolatile<typename UnConst<T>::Result >::Result UnqualifiedType;
156     typedef typename PointerTraits<UnqualifiedType>::PointeeType PointeeType;
157     typedef typename ReferenceTraits<T>::ReferredType ReferredType;
158 
159     enum { IsConst = UnConst<T>::IsConst };
160     enum { IsVolatile = UnVolatile<T>::IsVolatile };
161     enum { IsReference = ReferenceTraits<UnqualifiedType>::Result };
162     enum { IsPointer = PointerTraits<typename ReferenceTraits<UnqualifiedType>::ReferredType>::Result };
163     enum { IsMemberPointer = PointerToMemberTraits<typename ReferenceTraits<UnqualifiedType>::ReferredType>::Result };
164     enum { IsStandardUnsignedInt = TL::IndexOf<Types::StandardUnsignedInts, UnqualifiedType>::Value >= 0 ||
165       TL::IndexOf<Types::StandardUnsignedInts, typename ReferenceTraits<UnqualifiedType>::ReferredType>::Value >= 0 };
166     enum { IsStandardSignedInt = TL::IndexOf<Types::StandardSignedInts, UnqualifiedType>::Value >= 0 ||
167       TL::IndexOf<Types::StandardSignedInts, typename ReferenceTraits<UnqualifiedType>::ReferredType>::Value >= 0 };
168     enum { IsStandardIntegral = IsStandardUnsignedInt || IsStandardSignedInt ||
169       TL::IndexOf<Types::StandardOtherInts, UnqualifiedType>::Value >= 0 ||
170       TL::IndexOf<Types::StandardOtherInts, typename ReferenceTraits<UnqualifiedType>::ReferredType>::Value >= 0 };
171     enum { IsStandardFloatingPoint = TL::IndexOf<Types::StandardFloatingPoint, UnqualifiedType>::Value >= 0 ||
172       TL::IndexOf<Types::StandardFloatingPoint, typename ReferenceTraits<UnqualifiedType>::ReferredType>::Value >= 0 };
173     enum { IsStandardArithmetic = IsStandardIntegral || IsStandardFloatingPoint };
174     enum { IsIntegral = IsStandardIntegral };
175     enum { IsFloatingPoint = IsStandardFloatingPoint };
176     enum { IsArithmetic = IsIntegral || IsFloatingPoint };
177 
178     typedef typename TypeSelect<
179       IsArithmetic || IsPointer || IsMemberPointer,
180       T,
181       typename Internal::MakeParameterType<T>::Result
182     >::Result ParameterType;
183   };
184 };
185 
186 #endif
187