|
Sierra Toolkit
Version of the Day
|
00001 /* 00002 Copyright (C) 2005,2009-2010 Electronic Arts, Inc. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions 00006 are met: 00007 00008 1. Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 2. Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in the 00012 documentation and/or other materials provided with the distribution. 00013 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of 00014 its contributors may be used to endorse or promote products derived 00015 from this software without specific prior written permission. 00016 00017 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY 00018 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00020 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY 00021 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00026 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00030 // EASTL/internal/type_compound.h 00031 // Written and maintained by Paul Pedriana - 2005. 00033 00034 00035 #ifndef EASTL_INTERNAL_TYPE_COMPOUND_H 00036 #define EASTL_INTERNAL_TYPE_COMPOUND_H 00037 00038 00039 namespace eastl 00040 { 00041 00042 // The following properties or relations are defined here. If the given 00043 // item is missing then it simply hasn't been implemented, at least not yet. 00044 // is_array 00045 // is_pointer 00046 // is_reference 00047 // is_member_object_pointer 00048 // is_member_function_pointer 00049 // is_member_pointer 00050 // is_enum 00051 // is_union 00052 // is_class 00053 // is_polymorphic 00054 // is_function 00055 // is_object 00056 // is_scalar 00057 // is_compound 00058 // is_same 00059 // is_convertible 00060 00062 // is_array 00063 // 00064 // is_array<T>::value == true if and only if T is an array type. 00065 // As of this writing, the SNC compiler (EDG-based) doesn't compile 00066 // the code below and says that returning an array is illegal. 00067 // 00069 template <typename T> 00070 T (*is_array_tester1(empty<T>))(empty<T>); 00071 char is_array_tester1(...); // May need to use __cdecl under VC++. 00072 00073 template <typename T> 00074 no_type is_array_tester2(T(*)(empty<T>)); 00075 yes_type is_array_tester2(...); // May need to use __cdecl under VC++. 00076 00077 template <typename T> 00078 struct is_array_helper { 00079 static empty<T> emptyInstance; 00080 }; 00081 00082 template <typename T> 00083 struct is_array : public integral_constant<bool, 00084 sizeof(is_array_tester2(is_array_tester1(is_array_helper<T>::emptyInstance))) == 1 00085 >{}; 00086 00087 00088 00090 // is_reference 00091 // 00092 // is_reference<T>::value == true if and only if T is a reference type. 00093 // This category includes reference to function types. 00094 // 00096 template <typename T> struct is_reference : public false_type{}; 00097 template <typename T> struct is_reference<T&> : public true_type{}; 00098 00099 00100 00102 // is_member_function_pointer 00103 // 00104 // is_member_function_pointer<T>::value == true if and only if T is a 00105 // pointer to member function type. 00106 // 00108 // We detect member functions with 0 to N arguments. We can extend this 00109 // for additional arguments if necessary. 00110 // To do: Make volatile and const volatile versions of these in addition to non-const and const. 00112 template <typename T> struct is_mem_fun_pointer_value : public false_type{}; 00113 template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)()> : public true_type{}; 00114 template <typename R, typename T> struct is_mem_fun_pointer_value<R (T::*)() const> : public true_type{}; 00115 template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0)> : public true_type{}; 00116 template <typename R, typename T, typename Arg0> struct is_mem_fun_pointer_value<R (T::*)(Arg0) const> : public true_type{}; 00117 template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1)> : public true_type{}; 00118 template <typename R, typename T, typename Arg0, typename Arg1> struct is_mem_fun_pointer_value<R (T::*)(Arg0, Arg1) const> : public true_type{}; 00119 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{}; 00120 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{}; 00121 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{}; 00122 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{}; 00123 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{}; 00124 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{}; 00125 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{}; 00126 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{}; 00127 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{}; 00128 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{}; 00129 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{}; 00130 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{}; 00131 00132 template <typename T> 00133 struct is_member_function_pointer : public integral_constant<bool, is_mem_fun_pointer_value<T>::value>{}; 00134 00135 00137 // is_member_pointer 00138 // 00139 // is_member_pointer<T>::value == true if and only if: 00140 // is_member_object_pointer<T>::value == true, or 00141 // is_member_function_pointer<T>::value == true 00142 // 00144 template <typename T> 00145 struct is_member_pointer : public integral_constant<bool, is_member_function_pointer<T>::value>{}; 00146 00147 template <typename T, typename U> struct is_member_pointer<U T::*> : public true_type{}; 00148 00149 00150 00151 00153 // is_pointer 00154 // 00155 // is_pointer<T>::value == true if and only if T is a pointer type. 00156 // This category includes function pointer types, but not pointer to 00157 // member types. 00158 // 00160 template <typename T> struct is_pointer_helper : public false_type{}; 00161 00162 template <typename T> struct is_pointer_helper<T*> : public true_type{}; 00163 template <typename T> struct is_pointer_helper<T* const> : public true_type{}; 00164 template <typename T> struct is_pointer_helper<T* volatile> : public true_type{}; 00165 template <typename T> struct is_pointer_helper<T* const volatile> : public true_type{}; 00166 00167 template <typename T> 00168 struct is_pointer_value : public type_and<is_pointer_helper<T>::value, type_not<is_member_pointer<T>::value>::value> {}; 00169 00170 template <typename T> 00171 struct is_pointer : public integral_constant<bool, is_pointer_value<T>::value>{}; 00172 00173 00174 00176 // is_same 00177 // 00178 // Given two (possibly identical) types T and U, is_same<T, U>::value == true 00179 // if and only if T and U are the same type. 00180 // 00182 template<typename T, typename U> 00183 struct is_same : public false_type { }; 00184 00185 template<typename T> 00186 struct is_same<T, T> : public true_type { }; 00187 00188 00190 // is_convertible 00191 // 00192 // Given two (possible identical) types From and To, is_convertible<From, To>::value == true 00193 // if and only if an lvalue of type From can be implicitly converted to type To, 00194 // or is_void<To>::value == true 00195 // 00196 // is_convertible may only be applied to complete types. 00197 // Type To may not be an abstract type. 00198 // If the conversion is ambiguous, the program is ill-formed. 00199 // If either or both of From and To are class types, and the conversion would invoke 00200 // non-public member functions of either From or To (such as a private constructor of To, 00201 // or a private conversion operator of From), the program is ill-formed. 00202 // 00203 // Note that without compiler help, both is_convertible and is_base 00204 // can produce compiler errors if the conversion is ambiguous. 00205 // Example: 00206 // struct A {}; 00207 // struct B : A {}; 00208 // struct C : A {}; 00209 // struct D : B, C {}; 00210 // is_convertible<D*, A*>::value; // Generates compiler error. 00212 #if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x doesn't like the code below. 00213 template <typename From, typename To, bool is_from_void = false, bool is_to_void = false> 00214 struct is_convertible_helper { 00215 static yes_type Test(To); // May need to use __cdecl under VC++. 00216 static no_type Test(...); // May need to use __cdecl under VC++. 00217 static From from; 00218 typedef integral_constant<bool, sizeof(Test(from)) == sizeof(yes_type)> result; 00219 }; 00220 00221 // void is not convertible to non-void 00222 template <typename From, typename To> 00223 struct is_convertible_helper<From, To, true, false> { typedef false_type result; }; 00224 00225 // Anything is convertible to void 00226 template <typename From, typename To, bool is_from_void> 00227 struct is_convertible_helper<From, To, is_from_void, true> { typedef true_type result; }; 00228 00229 template <typename From, typename To> 00230 struct is_convertible : public is_convertible_helper<From, To, is_void<From>::value, is_void<To>::value>::result {}; 00231 00232 #else 00233 template <typename From, typename To> 00234 struct is_convertible : public false_type{}; 00235 #endif 00236 00237 00239 // is_union 00240 // 00241 // is_union<T>::value == true if and only if T is a union type. 00242 // 00243 // There is no way to tell if a type is a union without compiler help. 00244 // As of this writing, only Metrowerks v8+ supports such functionality 00245 // via 'msl::is_union<T>::value'. The user can force something to be 00246 // evaluated as a union via EASTL_DECLARE_UNION. 00248 template <typename T> struct is_union : public false_type{}; 00249 00250 #define EASTL_DECLARE_UNION(T) namespace eastl{ template <> struct is_union<T> : public true_type{}; template <> struct is_union<const T> : public true_type{}; } 00251 00252 00253 00254 00256 // is_class 00257 // 00258 // is_class<T>::value == true if and only if T is a class or struct 00259 // type (and not a union type). 00260 // 00261 // Without specific compiler help, it is not possible to 00262 // distinguish between unions and classes. As a result, is_class 00263 // will erroneously evaluate to true for union types. 00265 #if defined(__MWERKS__) 00266 // To do: Switch this to use msl_utility type traits. 00267 template <typename T> 00268 struct is_class : public false_type{}; 00269 #elif !defined(__GNUC__) || (((__GNUC__ * 100) + __GNUC_MINOR__) >= 304) // Not GCC or GCC 3.4+ 00270 template <typename U> static yes_type is_class_helper(void (U::*)()); 00271 template <typename U> static no_type is_class_helper(...); 00272 00273 template <typename T> 00274 struct is_class : public integral_constant<bool, 00275 sizeof(is_class_helper<T>(0)) == sizeof(yes_type) && !is_union<T>::value 00276 >{}; 00277 #else 00278 // GCC 2.x version, due to GCC being broken. 00279 template <typename T> 00280 struct is_class : public false_type{}; 00281 #endif 00282 00283 00284 00286 // is_enum 00287 // 00288 // is_enum<T>::value == true if and only if T is an enumeration type. 00289 // 00291 struct int_convertible{ int_convertible(int); }; 00292 00293 template <bool is_arithmetic_or_reference> 00294 struct is_enum_helper { template <typename T> struct nest : public is_convertible<T, int_convertible>{}; }; 00295 00296 template <> 00297 struct is_enum_helper<true> { template <typename T> struct nest : public false_type {}; }; 00298 00299 template <typename T> 00300 struct is_enum_helper2 00301 { 00302 typedef type_or<is_arithmetic<T>::value, is_reference<T>::value, is_class<T>::value> selector; 00303 typedef is_enum_helper<selector::value> helper_t; 00304 typedef typename add_reference<T>::type ref_t; 00305 typedef typename helper_t::template nest<ref_t> result; 00306 }; 00307 00308 template <typename T> 00309 struct is_enum : public integral_constant<bool, is_enum_helper2<T>::result::value>{}; 00310 00311 template <> struct is_enum<void> : public false_type {}; 00312 template <> struct is_enum<void const> : public false_type {}; 00313 template <> struct is_enum<void volatile> : public false_type {}; 00314 template <> struct is_enum<void const volatile> : public false_type {}; 00315 00316 #define EASTL_DECLARE_ENUM(T) namespace eastl{ template <> struct is_enum<T> : public true_type{}; template <> struct is_enum<const T> : public true_type{}; } 00317 00318 00320 // is_polymorphic 00321 // 00322 // is_polymorphic<T>::value == true if and only if T is a class or struct 00323 // that declares or inherits a virtual function. is_polymorphic may only 00324 // be applied to complete types. 00325 // 00327 template <typename T> 00328 struct is_polymorphic_imp1 00329 { 00330 typedef typename remove_cv<T>::type t; 00331 00332 struct helper_1 : public t 00333 { 00334 helper_1(); 00335 ~helper_1() throw(); 00336 char pad[64]; 00337 }; 00338 00339 struct helper_2 : public t 00340 { 00341 helper_2(); 00342 virtual ~helper_2() throw(); 00343 #ifndef _MSC_VER 00344 virtual void foo(); 00345 #endif 00346 char pad[64]; 00347 }; 00348 00349 static const bool value = (sizeof(helper_1) == sizeof(helper_2)); 00350 }; 00351 00352 template <typename T> 00353 struct is_polymorphic_imp2{ static const bool value = false; }; 00354 00355 template <bool is_class> 00356 struct is_polymorphic_selector{ template <typename T> struct rebind{ typedef is_polymorphic_imp2<T> type; }; }; 00357 00358 template <> 00359 struct is_polymorphic_selector<true>{ template <typename T> struct rebind{ typedef is_polymorphic_imp1<T> type; }; }; 00360 00361 template <typename T> 00362 struct is_polymorphic_value{ 00363 typedef is_polymorphic_selector<is_class<T>::value> selector; 00364 typedef typename selector::template rebind<T> binder; 00365 typedef typename binder::type imp_type; 00366 static const bool value = imp_type::value; 00367 }; 00368 00369 template <typename T> 00370 struct is_polymorphic : public integral_constant<bool, is_polymorphic_value<T>::value>{}; 00371 00372 00373 00374 00376 // is_function 00377 // 00378 // is_function<T>::value == true if and only if T is a function type. 00379 // 00381 template <typename R> struct is_function_ptr_helper : public false_type{}; 00382 template <typename R> struct is_function_ptr_helper<R (*)()> : public true_type{}; 00383 template <typename R, typename Arg0> struct is_function_ptr_helper<R (*)(Arg0)> : public true_type{}; 00384 template <typename R, typename Arg0, typename Arg1> struct is_function_ptr_helper<R (*)(Arg0, Arg1)> : public true_type{}; 00385 template <typename R, typename Arg0, typename Arg1, typename Arg2> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2)> : public true_type{}; 00386 template <typename R, typename Arg0, typename Arg1, typename Arg2, typename Arg3> struct is_function_ptr_helper<R (*)(Arg0, Arg1, Arg2, Arg3)> : public true_type{}; 00387 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{}; 00388 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{}; 00389 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{}; 00390 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{}; 00391 00392 template <bool is_ref = true> 00393 struct is_function_chooser{ template <typename T> struct result_ : public false_type{}; }; 00394 00395 template <> 00396 struct is_function_chooser<false>{ template <typename T> struct result_ : public is_function_ptr_helper<T*>{}; }; 00397 00398 template <typename T> 00399 struct is_function_value : public is_function_chooser<is_reference<T>::value>::template result_<T>{}; 00400 00401 template <typename T> 00402 struct is_function : public integral_constant<bool, is_function_value<T>::value>{}; 00403 00404 00405 00406 00408 // is_object 00409 // 00410 // is_object<T>::value == true if and only if: 00411 // is_reference<T>::value == false, and 00412 // is_function<T>::value == false, and 00413 // is_void<T>::value == false 00414 // 00415 // The C++ standard, section 3.9p9, states: "An object type is a 00416 // (possibly cv-qualified) type that is not a function type, not a 00417 // reference type, and not incomplete (except for an incompletely 00418 // defined object type). 00420 00421 template <typename T> 00422 struct is_object : public integral_constant<bool, 00423 !is_reference<T>::value && !is_void<T>::value && !is_function<T>::value 00424 >{}; 00425 00426 00427 00429 // is_scalar 00430 // 00431 // is_scalar<T>::value == true if and only if: 00432 // is_arithmetic<T>::value == true, or 00433 // is_enum<T>::value == true, or 00434 // is_pointer<T>::value == true, or 00435 // is_member_pointer<T>::value 00436 // 00438 template <typename T> 00439 struct is_scalar : public integral_constant<bool, is_arithmetic<T>::value || is_enum<T>::value>{}; 00440 00441 template <typename T> struct is_scalar<T*> : public true_type {}; 00442 template <typename T> struct is_scalar<T* const> : public true_type {}; 00443 template <typename T> struct is_scalar<T* volatile> : public true_type {}; 00444 template <typename T> struct is_scalar<T* const volatile> : public true_type {}; 00445 00446 00447 00449 // is_compound 00450 // 00451 // Compound means anything but fundamental. See C++ standard, section 3.9.2. 00452 // 00453 // is_compound<T>::value == true if and only if: 00454 // is_fundamental<T>::value == false 00455 // 00456 // Thus, is_compound<T>::value == true if and only if: 00457 // is_floating_point<T>::value == false, and 00458 // is_integral<T>::value == false, and 00459 // is_void<T>::value == false 00460 // 00462 template <typename T> 00463 struct is_compound : public integral_constant<bool, !is_fundamental<T>::value>{}; 00464 00465 00466 } // namespace eastl 00467 00468 00469 #endif // Header include guard