1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
11 // The author or Addison-Welsey Longman make no representations about the
12 // suitability of this software for any purpose. It is provided "as is"
13 // without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15
16 // Last update: June 20, 2001
17
18 #ifndef TYPEMANIP_INC_
19 #define TYPEMANIP_INC_
20
21 namespace Loki
22 {
23 ////////////////////////////////////////////////////////////////////////////////
24 // class template Int2Type
25 // Converts each integral constant into a unique type
26 // Invocation: Int2Type<v> where v is a compile-time constant integral
27 // Defines 'value', an enum that evaluates to v
28 ////////////////////////////////////////////////////////////////////////////////
29
30 template <int v>
31 struct Int2Type
32 {
33 enum { value = v };
34 };
35
36 ////////////////////////////////////////////////////////////////////////////////
37 // class template Type2Type
38 // Converts each type into a unique, insipid type
39 // Invocation Type2Type<T> where T is a type
40 // Defines the type OriginalType which maps back to T
41 ////////////////////////////////////////////////////////////////////////////////
42
43 template <typename T>
44 struct Type2Type
45 {
46 typedef T OriginalType;
47 };
48
49 ////////////////////////////////////////////////////////////////////////////////
50 // class template Select
51 // Selects one of two types based upon a boolean constant
52 // Invocation: Select<flag, T, U>::Result
53 // where:
54 // flag is a compile-time boolean constant
55 // T and U are types
56 // Result evaluates to T if flag is true, and to U otherwise.
57 ////////////////////////////////////////////////////////////////////////////////
58
59 template <bool flag, typename T, typename U>
60 struct Select
61 {
62 typedef T Result;
63 };
64 template <typename T, typename U>
65 struct Select<false, T, U>
66 {
67 typedef U Result;
68 };
69
70 ////////////////////////////////////////////////////////////////////////////////
71 // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
72 ////////////////////////////////////////////////////////////////////////////////
73
74 namespace Private
75 {
76 template <class T, class U>
77 struct ConversionHelper
78 {
79 typedef char Small;
80 struct Big { char dummy[2]; };
81 static Big Test(...);
82 static Small Test(U);
83 static T MakeT();
84 };
85 }
86
87 ////////////////////////////////////////////////////////////////////////////////
88 // class template Conversion
89 // Figures out the conversion relationships between two types
90 // Invocations (T and U are types):
91 // a) Conversion<T, U>::exists
92 // returns (at compile time) true if there is an implicit conversion from T
93 // to U (example: Derived to Base)
94 // b) Conversion<T, U>::exists2Way
95 // returns (at compile time) true if there are both conversions from T
96 // to U and from U to T (example: int to char and back)
97 // c) Conversion<T, U>::sameType
98 // returns (at compile time) true if T and U represent the same type
99 //
100 // Caveat: might not work if T and U are in a private inheritance hierarchy.
101 ////////////////////////////////////////////////////////////////////////////////
102
103 template <class T, class U>
104 struct Conversion
105 {
106 typedef Private::ConversionHelper<T, U> H;
107 #ifndef __MWERKS__
108 enum { exists = sizeof(typename H::Small) == sizeof(H::Test(H::MakeT())) };
109 #else
110 enum { exists = false };
111 #endif
112 enum { exists2Way = exists && Conversion<U, T>::exists };
113 enum { sameType = false };
114 };
115
116 template <class T>
117 struct Conversion<T, T>
118 {
119 enum { exists = 1, exists2Way = 1,sameType = 1 };
120 };
121
122 template <class T>
123 struct Conversion<void, T>
124 {
125 enum { exists = 1, exists2Way = 0,sameType = 0 };
126 };
127
128 template <class T>
129 struct Conversion<T, void>
130 {
131 enum { exists = 1, exists2Way = 0,sameType = 0 };
132 };
133
134 template <>
135 class Conversion<void, void>
136 {
137 public:
138 enum { exists = 1, exists2Way = 1,sameType = 1 };
139 };
140 }
141
142 ////////////////////////////////////////////////////////////////////////////////
143 // macro SUPERSUBCLASS
144 // Invocation: SUPERSUBCLASS(B, D) where B and D are types.
145 // Returns true if B is a public base of D, or if B and D are aliases of the
146 // same type.
147 //
148 // Caveat: might not work if T and U are in a private inheritance hierarchy.
149 ////////////////////////////////////////////////////////////////////////////////
150
151 #define SUPERSUBCLASS(T, U) \
152 (::Loki::Conversion<const U*, const T*>::exists && \
153 !::Loki::Conversion<const T*, const void*>::sameType)
154
155 ////////////////////////////////////////////////////////////////////////////////
156 // macro SUPERSUBCLASS
157 // Invocation: SUPERSUBCLASS(B, D) where B and D are types.
158 // Returns true if B is a public base of D.
159 //
160 // Caveat: might not work if T and U are in a private inheritance hierarchy.
161 ////////////////////////////////////////////////////////////////////////////////
162
163 #define SUPERSUBCLASS_STRICT(T, U) \
164 (SUPERSUBCLASS(T, U) && \
165 !::Loki::Conversion<const T, const U>::sameType)
166
167 ////////////////////////////////////////////////////////////////////////////////
168 // Change log:
169 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
170 ////////////////////////////////////////////////////////////////////////////////
171
172 #endif // TYPEMANIP_INC_