Sierra Toolkit Version of the Day
type_compound_eastl.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends