1 type_traits.h |
1 /* |
|
2 * |
|
3 * Copyright (c) 1996,1997 |
|
4 * Silicon Graphics Computer Systems, Inc. |
|
5 * |
|
6 * Copyright (c) 1997 |
|
7 * Moscow Center for SPARC Technology |
|
8 * |
|
9 * Copyright (c) 1999 |
|
10 * Boris Fomitchev |
|
11 * |
|
12 * This material is provided "as is", with absolutely no warranty expressed |
|
13 * or implied. Any use is at your own risk. |
|
14 * |
|
15 * Permission to use or copy this software for any purpose is hereby granted |
|
16 * without fee, provided the above notices are retained on all copies. |
|
17 * Permission to modify the code and to distribute modified code is granted, |
|
18 * provided the above notices are retained, and a notice that the code was |
|
19 * modified is included with the above copyright notice. |
|
20 * |
|
21 */ |
|
22 |
|
23 #ifndef _STLP_TYPE_TRAITS_H |
|
24 #define _STLP_TYPE_TRAITS_H |
|
25 |
|
26 /* |
|
27 This header file provides a framework for allowing compile time dispatch |
|
28 based on type attributes. This is useful when writing template code. |
|
29 For example, when making a copy of an array of an unknown type, it helps |
|
30 to know if the type has a trivial copy constructor or not, to help decide |
|
31 if a memcpy can be used. |
|
32 |
|
33 The class template __type_traits provides a series of typedefs each of |
|
34 which is either __true_type or __false_type. The argument to |
|
35 __type_traits can be any type. The typedefs within this template will |
|
36 attain their correct values by one of these means: |
|
37 1. The general instantiation contain conservative values which work |
|
38 for all types. |
|
39 2. Specializations may be declared to make distinctions between types. |
|
40 3. Some compilers (such as the Silicon Graphics N32 and N64 compilers) |
|
41 will automatically provide the appropriate specializations for all |
|
42 types. |
|
43 |
|
44 EXAMPLE: |
|
45 |
|
46 //Copy an array of elements which have non-trivial copy constructors |
|
47 template <class T> void copy(T* source, T* destination, int n, __false_type); |
|
48 //Copy an array of elements which have trivial copy constructors. Use memcpy. |
|
49 template <class T> void copy(T* source, T* destination, int n, __true_type); |
|
50 |
|
51 //Copy an array of any type by using the most efficient copy mechanism |
|
52 template <class T> inline void copy(T* source,T* destination,int n) { |
|
53 copy(source, destination, n, |
|
54 typename __type_traits<T>::has_trivial_copy_constructor()); |
|
55 } |
|
56 */ |
|
57 |
|
58 #ifdef __WATCOMC__ |
|
59 # include <stl/_cwchar.h> |
|
60 #endif |
|
61 |
|
62 _STLP_BEGIN_NAMESPACE |
|
63 |
|
64 struct __true_type {}; |
|
65 struct __false_type {}; |
|
66 |
|
67 |
|
68 template <int _Is> struct __bool2type { |
|
69 typedef __false_type _Ret; |
|
70 }; |
|
71 |
|
72 _STLP_TEMPLATE_NULL |
|
73 struct __bool2type<1> { typedef __true_type _Ret; }; |
|
74 |
|
75 _STLP_TEMPLATE_NULL |
|
76 struct __bool2type<0> { typedef __false_type _Ret; }; |
|
77 |
|
78 // logical end of 3 predicated |
|
79 template <class _P1, class _P2, class _P3> |
|
80 struct _Land3 { |
|
81 typedef __false_type _Ret; |
|
82 }; |
|
83 |
|
84 _STLP_TEMPLATE_NULL |
|
85 struct _Land3<__true_type, __true_type, __true_type> { |
|
86 typedef __true_type _Ret; |
|
87 }; |
|
88 |
|
89 |
|
90 // Forward declarations. |
|
91 template <class _Tp> struct __type_traits; |
|
92 template <int _IsPOD> struct __type_traits_aux { |
|
93 typedef __false_type has_trivial_default_constructor; |
|
94 typedef __false_type has_trivial_copy_constructor; |
|
95 typedef __false_type has_trivial_assignment_operator; |
|
96 typedef __false_type has_trivial_destructor; |
|
97 typedef __false_type is_POD_type; |
|
98 }; |
|
99 |
|
100 _STLP_TEMPLATE_NULL |
|
101 struct __type_traits_aux<0> { |
|
102 typedef __false_type has_trivial_default_constructor; |
|
103 typedef __false_type has_trivial_copy_constructor; |
|
104 typedef __false_type has_trivial_assignment_operator; |
|
105 typedef __false_type has_trivial_destructor; |
|
106 typedef __false_type is_POD_type; |
|
107 }; |
|
108 |
|
109 _STLP_TEMPLATE_NULL |
|
110 struct __type_traits_aux<1> { |
|
111 typedef __true_type has_trivial_default_constructor; |
|
112 typedef __true_type has_trivial_copy_constructor; |
|
113 typedef __true_type has_trivial_assignment_operator; |
|
114 typedef __true_type has_trivial_destructor; |
|
115 typedef __true_type is_POD_type; |
|
116 }; |
|
117 |
|
118 # ifdef _STLP_SIMULATE_PARTIAL_SPEC_FOR_TYPE_TRAITS |
|
119 |
|
120 // Boris : simulation technique is used here according to Adobe Open Source License Version 1.0. |
|
121 // Copyright 2000 Adobe Systems Incorporated and others. All rights reserved. |
|
122 // Authors: Mat Marcus and Jesse Jones |
|
123 // The original version of this source code may be found at |
|
124 // http://opensource.adobe.com. |
|
125 |
|
126 struct _PointerShim { |
|
127 // Since the compiler only allows at most one non-trivial |
|
128 // implicit conversion we can make use of a shim class to |
|
129 // be sure that IsPtr below doesn't accept classes with |
|
130 // implicit pointer conversion operators |
|
131 _PointerShim(const volatile void*); // no implementation |
|
132 }; |
|
133 |
|
134 // These are the discriminating functions |
|
135 |
|
136 char _STLP_CALL _IsP(bool, _PointerShim); // no implementation is required |
|
137 char* _STLP_CALL _IsP(bool, ...); // no implementation is required |
|
138 |
|
139 template <class _Tp> |
|
140 char _STLP_CALL _IsSameFun(bool, _Tp*, _Tp*); // no implementation is required |
|
141 char* _STLP_CALL _IsSameFun(bool, ...); // no implementation is required |
|
142 |
|
143 template <class _Tp1, class _Tp2> |
|
144 struct _IsSame { |
|
145 // boris : check! |
|
146 static _Tp1* __null_rep1(); |
|
147 static _Tp2* __null_rep2(); |
|
148 enum { _Ret = (sizeof(_IsSameFun(false,__null_rep1(),__null_rep2())) == sizeof(char)) }; |
|
149 }; |
|
150 |
|
151 template <class _Tp> |
|
152 struct _IsPtr { |
|
153 |
|
154 // This template meta function takes a type T |
|
155 // and returns true exactly when T is a pointer. |
|
156 // One can imagine meta-functions discriminating on |
|
157 // other criteria. |
|
158 static _Tp& __null_rep(); |
|
159 enum { _Ret = (sizeof(_IsP(false,__null_rep())) == sizeof(char)) }; |
|
160 |
|
161 }; |
|
162 |
|
163 template <class _Tp> |
|
164 struct _IsPtrType { |
|
165 enum { _Is = _IsPtr<_Tp>::_Ret } ; |
|
166 typedef __bool2type< _Is > _BT; |
|
167 typedef typename _BT::_Ret _Type; |
|
168 static _Type _Ret() { return _Type(); } |
|
169 }; |
|
170 |
|
171 template <class _Tp1, class _Tp2> |
|
172 struct _BothPtrType { |
|
173 typedef __bool2type< _IsPtr<_Tp1>::_Ret> _B1; |
|
174 typedef __bool2type< _IsPtr<_Tp2>::_Ret> _B2; |
|
175 typedef typename _B1::_Ret _Type1; |
|
176 typedef typename _B2::_Ret _Type2; |
|
177 typedef typename _Land3<_Type1, _Type2, __true_type>::_Ret _Type; |
|
178 static _Type _Ret() { return _Type(); } |
|
179 }; |
|
180 |
|
181 // we make general case dependant on the fact the type is actually a pointer. |
|
182 |
|
183 template <class _Tp> |
|
184 struct __type_traits : __type_traits_aux<_IsPtr<_Tp>::_Ret> {}; |
|
185 |
|
186 # else |
|
187 |
|
188 template <class _Tp> |
|
189 struct __type_traits { |
|
190 typedef __true_type this_dummy_member_must_be_first; |
|
191 /* Do not remove this member. It informs a compiler which |
|
192 automatically specializes __type_traits that this |
|
193 __type_traits template is special. It just makes sure that |
|
194 things work if an implementation is using a template |
|
195 called __type_traits for something unrelated. */ |
|
196 |
|
197 /* The following restrictions should be observed for the sake of |
|
198 compilers which automatically produce type specific specializations |
|
199 of this class: |
|
200 - You may reorder the members below if you wish |
|
201 - You may remove any of the members below if you wish |
|
202 - You must not rename members without making the corresponding |
|
203 name change in the compiler |
|
204 - Members you add will be treated like regular members unless |
|
205 you add the appropriate support in the compiler. */ |
|
206 typedef __false_type has_trivial_default_constructor; |
|
207 typedef __false_type has_trivial_copy_constructor; |
|
208 typedef __false_type has_trivial_assignment_operator; |
|
209 typedef __false_type has_trivial_destructor; |
|
210 typedef __false_type is_POD_type; |
|
211 }; |
|
212 |
|
213 |
|
214 template <class _Tp> struct _IsPtr { enum { _Ret = 0 }; }; |
|
215 template <class _Tp> struct _IsPtrType { |
|
216 static __false_type _Ret() { return __false_type();} |
|
217 }; |
|
218 template <class _Tp1, class _Tp2> struct _BothPtrType { |
|
219 static __false_type _Ret() { return __false_type();} |
|
220 }; |
|
221 |
|
222 template <class _Tp1, class _Tp2> |
|
223 struct _IsSame { enum { _Ret = 0 }; }; |
|
224 |
|
225 // template <class _Tp1, class _Tp2> |
|
226 // struct _IsSameType { static __false_type _Ret() { return __false_type(); } }; |
|
227 |
|
228 # ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION |
|
229 template <class _Tp> struct _IsPtr<_Tp*> { enum { _Ret = 1 }; }; |
|
230 template <class _Tp> struct _IsPtrType<_Tp*> { |
|
231 static __true_type _Ret() { return __true_type();} |
|
232 }; |
|
233 template <class _Tp1, class _Tp2> struct _BothPtrType<_Tp1*, _Tp2*> { |
|
234 static __true_type _Ret() { return __true_type();} |
|
235 }; |
|
236 template <class _Tp> |
|
237 struct _IsSame<_Tp, _Tp> { enum { _Ret = 1 }; }; |
|
238 # endif |
|
239 |
|
240 # endif /* _STLP_SIMULATE_PARTIAL_SPEC_FOR_TYPE_TRAITS */ |
|
241 |
|
242 // Provide some specializations. This is harmless for compilers that |
|
243 // have built-in __types_traits support, and essential for compilers |
|
244 // that don't. |
|
245 #ifndef _STLP_NO_BOOL |
|
246 _STLP_TEMPLATE_NULL struct __type_traits<bool> : __type_traits_aux<1> {}; |
|
247 #endif /* _STLP_NO_BOOL */ |
|
248 _STLP_TEMPLATE_NULL struct __type_traits<char> : __type_traits_aux<1> {}; |
|
249 #ifndef _STLP_NO_SIGNED_BUILTINS |
|
250 _STLP_TEMPLATE_NULL struct __type_traits<signed char> : __type_traits_aux<1> {}; |
|
251 # endif |
|
252 _STLP_TEMPLATE_NULL struct __type_traits<unsigned char> : __type_traits_aux<1> {}; |
|
253 #if defined ( _STLP_HAS_WCHAR_T ) && ! defined (_STLP_WCHAR_T_IS_USHORT) |
|
254 _STLP_TEMPLATE_NULL struct __type_traits<wchar_t> : __type_traits_aux<1> {}; |
|
255 #endif /* _STLP_HAS_WCHAR_T */ |
|
256 |
|
257 _STLP_TEMPLATE_NULL struct __type_traits<short> : __type_traits_aux<1> {}; |
|
258 _STLP_TEMPLATE_NULL struct __type_traits<unsigned short> : __type_traits_aux<1> {}; |
|
259 _STLP_TEMPLATE_NULL struct __type_traits<int> : __type_traits_aux<1> {}; |
|
260 _STLP_TEMPLATE_NULL struct __type_traits<unsigned int> : __type_traits_aux<1> {}; |
|
261 _STLP_TEMPLATE_NULL struct __type_traits<long> : __type_traits_aux<1> {}; |
|
262 _STLP_TEMPLATE_NULL struct __type_traits<unsigned long> : __type_traits_aux<1> {}; |
|
263 |
|
264 #ifdef _STLP_LONG_LONG |
|
265 _STLP_TEMPLATE_NULL struct __type_traits<_STLP_LONG_LONG> : __type_traits_aux<1> {}; |
|
266 _STLP_TEMPLATE_NULL struct __type_traits<unsigned _STLP_LONG_LONG> : __type_traits_aux<1> {}; |
|
267 #endif /* _STLP_LONG_LONG */ |
|
268 |
|
269 _STLP_TEMPLATE_NULL struct __type_traits<float> : __type_traits_aux<1> {}; |
|
270 _STLP_TEMPLATE_NULL struct __type_traits<double> : __type_traits_aux<1> {}; |
|
271 |
|
272 # if !defined ( _STLP_NO_LONG_DOUBLE ) |
|
273 _STLP_TEMPLATE_NULL struct __type_traits<long double> : __type_traits_aux<1> {}; |
|
274 # endif |
|
275 |
|
276 #ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION |
|
277 template <class _Tp> struct __type_traits<_Tp*> : __type_traits_aux<1> {}; |
|
278 #endif |
|
279 |
|
280 // The following could be written in terms of numeric_limits. |
|
281 // We're doing it separately to reduce the number of dependencies. |
|
282 |
|
283 template <class _Tp> struct _Is_integer { |
|
284 typedef __false_type _Integral; |
|
285 }; |
|
286 |
|
287 #ifndef _STLP_NO_BOOL |
|
288 |
|
289 _STLP_TEMPLATE_NULL struct _Is_integer<bool> { |
|
290 typedef __true_type _Integral; |
|
291 }; |
|
292 |
|
293 #endif /* _STLP_NO_BOOL */ |
|
294 |
|
295 _STLP_TEMPLATE_NULL struct _Is_integer<char> { |
|
296 typedef __true_type _Integral; |
|
297 }; |
|
298 |
|
299 #ifndef _STLP_NO_SIGNED_BUILTINS |
|
300 |
|
301 _STLP_TEMPLATE_NULL struct _Is_integer<signed char> { |
|
302 typedef __true_type _Integral; |
|
303 }; |
|
304 #endif |
|
305 |
|
306 _STLP_TEMPLATE_NULL struct _Is_integer<unsigned char> { |
|
307 typedef __true_type _Integral; |
|
308 }; |
|
309 |
|
310 #if defined ( _STLP_HAS_WCHAR_T ) && ! defined (_STLP_WCHAR_T_IS_USHORT) |
|
311 |
|
312 _STLP_TEMPLATE_NULL struct _Is_integer<wchar_t> { |
|
313 typedef __true_type _Integral; |
|
314 }; |
|
315 |
|
316 #endif /* _STLP_HAS_WCHAR_T */ |
|
317 |
|
318 _STLP_TEMPLATE_NULL struct _Is_integer<short> { |
|
319 typedef __true_type _Integral; |
|
320 }; |
|
321 |
|
322 _STLP_TEMPLATE_NULL struct _Is_integer<unsigned short> { |
|
323 typedef __true_type _Integral; |
|
324 }; |
|
325 |
|
326 _STLP_TEMPLATE_NULL struct _Is_integer<int> { |
|
327 typedef __true_type _Integral; |
|
328 }; |
|
329 |
|
330 _STLP_TEMPLATE_NULL struct _Is_integer<unsigned int> { |
|
331 typedef __true_type _Integral; |
|
332 }; |
|
333 |
|
334 _STLP_TEMPLATE_NULL struct _Is_integer<long> { |
|
335 typedef __true_type _Integral; |
|
336 }; |
|
337 |
|
338 _STLP_TEMPLATE_NULL struct _Is_integer<unsigned long> { |
|
339 typedef __true_type _Integral; |
|
340 }; |
|
341 |
|
342 #ifdef _STLP_LONG_LONG |
|
343 |
|
344 _STLP_TEMPLATE_NULL struct _Is_integer<_STLP_LONG_LONG> { |
|
345 typedef __true_type _Integral; |
|
346 }; |
|
347 |
|
348 _STLP_TEMPLATE_NULL struct _Is_integer<unsigned _STLP_LONG_LONG> { |
|
349 typedef __true_type _Integral; |
|
350 }; |
|
351 |
|
352 #endif /* _STLP_LONG_LONG */ |
|
353 |
|
354 template <class _Tp1, class _Tp2> |
|
355 struct _OKToMemCpy { |
|
356 enum { _Same = _IsSame<_Tp1,_Tp2>::_Ret } ; |
|
357 typedef typename __type_traits<_Tp1>::has_trivial_assignment_operator _Tr1; |
|
358 typedef typename __type_traits<_Tp2>::has_trivial_assignment_operator _Tr2; |
|
359 typedef typename __bool2type< _Same >::_Ret _Tr3; |
|
360 typedef typename _Land3<_Tr1, _Tr2, _Tr3>::_Ret _Type; |
|
361 static _Type _Ret() { return _Type(); } |
|
362 }; |
|
363 |
|
364 template <class _Tp1, class _Tp2> |
|
365 inline _OKToMemCpy<_Tp1, _Tp2> _IsOKToMemCpy(_Tp1*, _Tp2*) { |
|
366 return _OKToMemCpy<_Tp1, _Tp2>(); |
|
367 } |
|
368 |
|
369 template <class _Tp> |
|
370 struct _IsPOD { |
|
371 typedef typename __type_traits<_Tp>::is_POD_type _Type; |
|
372 static _Type _Ret() { return _Type(); } |
|
373 }; |
|
374 |
|
375 template <class _Tp> |
|
376 inline _IsPOD<_Tp> _Is_POD (_Tp*) { return _IsPOD<_Tp>(); } |
|
377 |
|
378 # ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION |
|
379 # if defined (__BORLANDC__) || defined (__SUNPRO_CC) || ( defined (__MWERKS__) && (__MWERKS__ <= 0x2303)) || ( defined (__sgi) && defined (_COMPILER_VERSION)) || defined (__DMC__) |
|
380 # define _IS_POD_ITER(_It, _Tp) __type_traits< typename iterator_traits< _Tp >::value_type >::is_POD_type() |
|
381 # else |
|
382 # define _IS_POD_ITER(_It, _Tp) typename __type_traits< typename iterator_traits< _Tp >::value_type >::is_POD_type() |
|
383 # endif |
|
384 # else |
|
385 # define _IS_POD_ITER(_It, _Tp) _Is_POD( _STLP_VALUE_TYPE( _It, _Tp ) )._Ret() |
|
386 # endif |
|
387 |
|
388 # ifdef _STLP_DEFAULT_CONSTRUCTOR_BUG |
|
389 // Those adaptors are here to fix common compiler bug regarding builtins: |
|
390 // expressions like int k = int() should initialize k to 0 |
|
391 template <class _Tp> |
|
392 inline _Tp __default_constructed_aux(_Tp*, const __false_type&) { |
|
393 return _Tp(); |
|
394 } |
|
395 template <class _Tp> |
|
396 inline _Tp __default_constructed_aux(_Tp*, const __true_type&) { |
|
397 return _Tp(0); |
|
398 } |
|
399 |
|
400 template <class _Tp> |
|
401 inline _Tp __default_constructed(_Tp* __p) { |
|
402 typedef typename _Is_integer<_Tp>::_Integral _Is_Integral; |
|
403 return __default_constructed_aux(__p, _Is_Integral()); |
|
404 } |
|
405 |
|
406 # define _STLP_DEFAULT_CONSTRUCTED(_TTp) __default_constructed((_TTp*)0) |
|
407 # else |
|
408 # define _STLP_DEFAULT_CONSTRUCTED(_TTp) _TTp() |
|
409 # endif |
|
410 |
|
411 _STLP_END_NAMESPACE |
|
412 |
|
413 #endif /* __TYPE_TRAITS_H */ |
|
414 |
|
415 // Local Variables: |
|
416 // mode:C++ |
|
417 // End: |
|
418 |