Sierra Toolkit  Version of the Day
type_compound_eastl.h
1 /*
2 Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 
8 1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14  its contributors may be used to endorse or promote products derived
15  from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
30 // EASTL/internal/type_compound.h
31 // Written and maintained by Paul Pedriana - 2005.
33 
34 
35 #ifndef EASTL_INTERNAL_TYPE_COMPOUND_H
36 #define EASTL_INTERNAL_TYPE_COMPOUND_H
37 
38 
39 namespace eastl
40 {
41 
42  // The following properties or relations are defined here. If the given
43  // item is missing then it simply hasn't been implemented, at least not yet.
44  // is_array
45  // is_pointer
46  // is_reference
47  // is_member_object_pointer
48  // is_member_function_pointer
49  // is_member_pointer
50  // is_enum
51  // is_union
52  // is_class
53  // is_polymorphic
54  // is_function
55  // is_object
56  // is_scalar
57  // is_compound
58  // is_same
59  // is_convertible
60 
62  // is_array
63  //
64  // is_array<T>::value == true if and only if T is an array type.
65  // As of this writing, the SNC compiler (EDG-based) doesn't compile
66  // the code below and says that returning an array is illegal.
67  //
69  template <typename T>
70  T (*is_array_tester1(empty<T>))(empty<T>);
71  char is_array_tester1(...); // May need to use __cdecl under VC++.
72 
73  template <typename T>
74  no_type is_array_tester2(T(*)(empty<T>));
75  yes_type is_array_tester2(...); // May need to use __cdecl under VC++.
76 
77  template <typename T>
78  struct is_array_helper {
79  static empty<T> emptyInstance;
80  };
81 
82  template <typename T>
83  struct is_array : public integral_constant<bool,
84  sizeof(is_array_tester2(is_array_tester1(is_array_helper<T>::emptyInstance))) == 1
85  >{};
86 
87 
88 
90  // is_reference
91  //
92  // is_reference<T>::value == true if and only if T is a reference type.
93  // This category includes reference to function types.
94  //
96  template <typename T> struct is_reference : public false_type{};
97  template <typename T> struct is_reference<T&> : public true_type{};
98 
99 
100 
102  // is_member_function_pointer
103  //
104  // is_member_function_pointer<T>::value == true if and only if T is a
105  // pointer to member function type.
106  //
108  // We detect member functions with 0 to N arguments. We can extend this
109  // for additional arguments if necessary.
110  // To do: Make volatile and const volatile versions of these in addition to non-const and const.
112  template <typename T> struct is_mem_fun_pointer_value : public false_type{};
113  template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)()> : public true_type{};
114  template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)() const> : public true_type{};
115  template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0)> : public true_type{};
116  template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0) const> : public true_type{};
117  template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1)> : public true_type{};
118  template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1) const> : public true_type{};
119  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2)> : public true_type{};
120  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2) const> : public true_type{};
121  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3)> : public true_type{};
122  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3) const> : public true_type{};
123  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4)> : public true_type{};
124  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4) const> : public true_type{};
125  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)> : public true_type{};
126  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5) const> : public true_type{};
127  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> : public true_type{};
128  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const> : public true_type{};
129  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> : public true_type{};
130  template <typename R, typename T, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const> : public true_type{};
131 
132  template <typename T>
133  struct is_member_function_pointer : public integral_constant<bool, is_mem_fun_pointer_value<T>::value>{};
134 
135 
137  // is_member_pointer
138  //
139  // is_member_pointer<T>::value == true if and only if:
140  // is_member_object_pointer<T>::value == true, or
141  // is_member_function_pointer<T>::value == true
142  //
144  template <typename T>
145  struct is_member_pointer : public integral_constant<bool, is_member_function_pointer<T>::value>{};
146 
147  template <typename T, typename U> struct is_member_pointer<U T::*> : public true_type{};
148 
149 
150 
151 
153  // is_pointer
154  //
155  // is_pointer<T>::value == true if and only if T is a pointer type.
156  // This category includes function pointer types, but not pointer to
157  // member types.
158  //
160  template <typename T> struct is_pointer_helper : public false_type{};
161 
162  template <typename T> struct is_pointer_helper<T*> : public true_type{};
163  template <typename T> struct is_pointer_helper<T* const> : public true_type{};
164  template <typename T> struct is_pointer_helper<T* volatile> : public true_type{};
165  template <typename T> struct is_pointer_helper<T* const volatile> : public true_type{};
166 
167  template <typename T>
168  struct is_pointer_value : public type_and<is_pointer_helper<T>::value, type_not<is_member_pointer<T>::value>::value> {};
169 
170  template <typename T>
171  struct is_pointer : public integral_constant<bool, is_pointer_value<T>::value>{};
172 
173 
174 
176  // is_same
177  //
178  // Given two (possibly identical) types T and U, is_same<T, U>::value == true
179  // if and only if T and U are the same type.
180  //
182  template<typename T, typename U>
183  struct is_same : public false_type { };
184 
185  template<typename T>
186  struct is_same<T, T> : public true_type { };
187 
188 
190  // is_convertible
191  //
192  // Given two (possible identical) types From and To, is_convertible<From, To>::value == true
193  // if and only if an lvalue of type From can be implicitly converted to type To,
194  // or is_void<To>::value == true
195  //
196  // is_convertible may only be applied to complete types.
197  // Type To may not be an abstract type.
198  // If the conversion is ambiguous, the program is ill-formed.
199  // If either or both of From and To are class types, and the conversion would invoke
200  // non-public member functions of either From or To (such as a private constructor of To,
201  // or a private conversion operator of From), the program is ill-formed.
202  //
203  // Note that without compiler help, both is_convertible and is_base
204  // can produce compiler errors if the conversion is ambiguous.
205  // Example:
206  // struct A {};
207  // struct B : A {};
208  // struct C : A {};
209  // struct D : B, C {};
210  // is_convertible<D*, A*>::value; // Generates compiler error.
212  #if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x doesn't like the code below.
213  template <typename From, typename To, bool is_from_void = false, bool is_to_void = false>
214  struct is_convertible_helper {
215  static yes_type Test(To); // May need to use __cdecl under VC++.
216  static no_type Test(...); // May need to use __cdecl under VC++.
217  static From from;
218  typedef integral_constant<bool, sizeof(Test(from)) == sizeof(yes_type)> result;
219  };
220 
221  // void is not convertible to non-void
222  template <typename From, typename To>
223  struct is_convertible_helper<From, To, true, false> { typedef false_type result; };
224 
225  // Anything is convertible to void
226  template <typename From, typename To, bool is_from_void>
227  struct is_convertible_helper<From, To, is_from_void, true> { typedef true_type result; };
228 
229  template <typename From, typename To>
230  struct is_convertible : public is_convertible_helper<From, To, is_void<From>::value, is_void<To>::value>::result {};
231 
232  #else
233  template <typename From, typename To>
234  struct is_convertible : public false_type{};
235  #endif
236 
237 
239  // is_union
240  //
241  // is_union<T>::value == true if and only if T is a union type.
242  //
243  // There is no way to tell if a type is a union without compiler help.
244  // As of this writing, only Metrowerks v8+ supports such functionality
245  // via 'msl::is_union<T>::value'. The user can force something to be
246  // evaluated as a union via EASTL_DECLARE_UNION.
248  template <typename T> struct is_union : public false_type{};
249 
250  #define EASTL_DECLARE_UNION(T) namespace eastl{ template <> struct is_union<T> : public true_type{}; template <> struct is_union<const T> : public true_type{}; }
251 
252 
253 
254 
256  // is_class
257  //
258  // is_class<T>::value == true if and only if T is a class or struct
259  // type (and not a union type).
260  //
261  // Without specific compiler help, it is not possible to
262  // distinguish between unions and classes. As a result, is_class
263  // will erroneously evaluate to true for union types.
265  #if defined(__MWERKS__)
266  // To do: Switch this to use msl_utility type traits.
267  template <typename T>
268  struct is_class : public false_type{};
269  #elif !defined(__GNUC__) || (((__GNUC__ * 100) + __GNUC_MINOR__) >= 304) // Not GCC or GCC 3.4+
270  template <typename U> static yes_type is_class_helper(void (U::*)());
271  template <typename U> static no_type is_class_helper(...);
272 
273  template <typename T>
274  struct is_class : public integral_constant<bool,
275  sizeof(is_class_helper<T>(0)) == sizeof(yes_type) && !is_union<T>::value
276  >{};
277  #else
278  // GCC 2.x version, due to GCC being broken.
279  template <typename T>
280  struct is_class : public false_type{};
281  #endif
282 
283 
284 
286  // is_enum
287  //
288  // is_enum<T>::value == true if and only if T is an enumeration type.
289  //
291  struct int_convertible{ int_convertible(int); };
292 
293  template <bool is_arithmetic_or_reference>
294  struct is_enum_helper { template <typename T> struct nest : public is_convertible<T, int_convertible>{}; };
295 
296  template <>
297  struct is_enum_helper<true> { template <typename T> struct nest : public false_type {}; };
298 
299  template <typename T>
300  struct is_enum_helper2
301  {
302  typedef type_or<is_arithmetic<T>::value, is_reference<T>::value, is_class<T>::value> selector;
303  typedef is_enum_helper<selector::value> helper_t;
304  typedef typename add_reference<T>::type ref_t;
305  typedef typename helper_t::template nest<ref_t> result;
306  };
307 
308  template <typename T>
309  struct is_enum : public integral_constant<bool, is_enum_helper2<T>::result::value>{};
310 
311  template <> struct is_enum<void> : public false_type {};
312  template <> struct is_enum<void const> : public false_type {};
313  template <> struct is_enum<void volatile> : public false_type {};
314  template <> struct is_enum<void const volatile> : public false_type {};
315 
316  #define EASTL_DECLARE_ENUM(T) namespace eastl{ template <> struct is_enum<T> : public true_type{}; template <> struct is_enum<const T> : public true_type{}; }
317 
318 
320  // is_polymorphic
321  //
322  // is_polymorphic<T>::value == true if and only if T is a class or struct
323  // that declares or inherits a virtual function. is_polymorphic may only
324  // be applied to complete types.
325  //
327  template <typename T>
328  struct is_polymorphic_imp1
329  {
330  typedef typename remove_cv<T>::type t;
331 
332  struct helper_1 : public t
333  {
334  helper_1();
335  ~helper_1() throw();
336  char pad[64];
337  };
338 
339  struct helper_2 : public t
340  {
341  helper_2();
342  virtual ~helper_2() throw();
343  #ifndef _MSC_VER
344  virtual void foo();
345  #endif
346  char pad[64];
347  };
348 
349  static const bool value = (sizeof(helper_1) == sizeof(helper_2));
350  };
351 
352  template <typename T>
353  struct is_polymorphic_imp2{ static const bool value = false; };
354 
355  template <bool is_class>
356  struct is_polymorphic_selector{ template <typename T> struct rebind{ typedef is_polymorphic_imp2<T> type; }; };
357 
358  template <>
359  struct is_polymorphic_selector<true>{ template <typename T> struct rebind{ typedef is_polymorphic_imp1<T> type; }; };
360 
361  template <typename T>
362  struct is_polymorphic_value{
363  typedef is_polymorphic_selector<is_class<T>::value> selector;
364  typedef typename selector::template rebind<T> binder;
365  typedef typename binder::type imp_type;
366  static const bool value = imp_type::value;
367  };
368 
369  template <typename T>
370  struct is_polymorphic : public integral_constant<bool, is_polymorphic_value<T>::value>{};
371 
372 
373 
374 
376  // is_function
377  //
378  // is_function<T>::value == true if and only if T is a function type.
379  //
381  template <typename R> struct is_function_ptr_helper : public false_type{};
382  template <typename R> struct is_function_ptr_helper<R (*)()> : public true_type{};
383  template <typename R, typename Arg0> struct is_function_ptr_helper<R (*)(Arg0)> : public true_type{};
384  template <typename R, typename Arg0, typename Arg1> struct is_function_ptr_helper<R (*)(Arg0, Arg1)> : public true_type{};
385  template <typename R, typename Arg0, typename Arg1, typename Arg2> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2)> : public true_type{};
386  template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3)> : public true_type{};
387  template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4)> : public true_type{};
388  template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)> : public true_type{};
389  template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> : public true_type{};
390  template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6, typename Arg7> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> : public true_type{};
391 
392  template <bool is_ref = true>
393  struct is_function_chooser{ template <typename T> struct result_ : public false_type{}; };
394 
395  template <>
396  struct is_function_chooser<false>{ template <typename T> struct result_ : public is_function_ptr_helper<T*>{}; };
397 
398  template <typename T>
399  struct is_function_value : public is_function_chooser<is_reference<T>::value>::template result_<T>{};
400 
401  template <typename T>
402  struct is_function : public integral_constant<bool, is_function_value<T>::value>{};
403 
404 
405 
406 
408  // is_object
409  //
410  // is_object<T>::value == true if and only if:
411  // is_reference<T>::value == false, and
412  // is_function<T>::value == false, and
413  // is_void<T>::value == false
414  //
415  // The C++ standard, section 3.9p9, states: "An object type is a
416  // (possibly cv-qualified) type that is not a function type, not a
417  // reference type, and not incomplete (except for an incompletely
418  // defined object type).
420 
421  template <typename T>
422  struct is_object : public integral_constant<bool,
423  !is_reference<T>::value && !is_void<T>::value && !is_function<T>::value
424  >{};
425 
426 
427 
429  // is_scalar
430  //
431  // is_scalar<T>::value == true if and only if:
432  // is_arithmetic<T>::value == true, or
433  // is_enum<T>::value == true, or
434  // is_pointer<T>::value == true, or
435  // is_member_pointer<T>::value
436  //
438  template <typename T>
439  struct is_scalar : public integral_constant<bool, is_arithmetic<T>::value || is_enum<T>::value>{};
440 
441  template <typename T> struct is_scalar<T*> : public true_type {};
442  template <typename T> struct is_scalar<T* const> : public true_type {};
443  template <typename T> struct is_scalar<T* volatile> : public true_type {};
444  template <typename T> struct is_scalar<T* const volatile> : public true_type {};
445 
446 
447 
449  // is_compound
450  //
451  // Compound means anything but fundamental. See C++ standard, section 3.9.2.
452  //
453  // is_compound<T>::value == true if and only if:
454  // is_fundamental<T>::value == false
455  //
456  // Thus, is_compound<T>::value == true if and only if:
457  // is_floating_point<T>::value == false, and
458  // is_integral<T>::value == false, and
459  // is_void<T>::value == false
460  //
462  template <typename T>
463  struct is_compound : public integral_constant<bool, !is_fundamental<T>::value>{};
464 
465 
466 } // namespace eastl
467 
468 
469 #endif // Header include guard
EA Standard Template Library.