00001 #ifndef __IS_BASE_OF_HH__ 00002 #define __IS_BASE_OF_HH__ 00003 00004 #include "fastjet/internal/numconsts.hh" 00005 00006 FASTJET_BEGIN_NAMESPACE 00007 00008 //--------------------------------------------------- 00009 // define a true and a false 'type' 00010 // Note: 00011 // we could actually template the type and recover 00012 // the TR1 integral_constant type. This also 00013 // includes adding a typedef for the type and a 00014 // typedef for the struct in the struct below 00015 // 00016 // This is going to be helpful to "split" a given 00017 // call into 2 options based on a type constraint 00018 // at compilation-time (rather than doing an "if" 00019 // which would only be resolved at runtime and could 00020 // thus resutl in compilation errors. 00021 //--------------------------------------------------- 00022 00023 /// \if internal_doc 00024 /// \class integral type 00025 /// a generic construct that promotes a generic value of a generic type 00026 /// as a type 00027 /// 00028 /// this has 2 template parameters: T, the considered type, and _t, a 00029 /// value of type T 00030 /// This object is a basic construct in type traits 00031 /// \endif 00032 template<typename T, T _t> 00033 struct integral_type{ 00034 static const T value = _t; ///< the value (only member carrying info) 00035 typedef T value_type; ///< a typedef for the type T 00036 typedef integral_type<T,_t> type; ///< a typedef for the whole structure 00037 }; 00038 00039 // definition of the static member in integral_type 00040 template<typename T, T _t> 00041 const T integral_type<T, _t>::value; 00042 00043 // shortcuts 00044 typedef integral_type<bool, true> true_type; ///< the bool 'true' value promoted to a type 00045 typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type 00046 00047 00048 //--------------------------------------------------- 00049 // define a yes and a no type (based on their size) 00050 //--------------------------------------------------- 00051 typedef char (&__yes_type)[1]; //< the yes type 00052 typedef char (&__no_type) [2]; //< the no type 00053 00054 00055 //--------------------------------------------------- 00056 // Now deal with inheritance checks 00057 // 00058 // We want to provide a IsBaseAndDerived<B,D> type 00059 // trait that contains a value that is true if D 00060 // is derived from B and false otherwise. 00061 // 00062 // For an explanation of how the code below works, 00063 // have a look at 00064 // http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83 00065 // and the links therein 00066 // 00067 // WARNING: according to 'boost', this may have some 00068 // issues with MSVC7.1. See their code for a description 00069 // of the workaround used below 00070 //--------------------------------------------------- 00071 00072 /// \if internal_doc 00073 /// \class __inheritance_helper 00074 /// helper for IsBasedAndDerived<B,D> 00075 /// \endif 00076 template<typename B, typename D> 00077 struct __inheritance_helper{ 00078 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310)) // MSVC 7.1 00079 template <typename T> 00080 static __yes_type check_sig(D const volatile *, T); 00081 #else 00082 static __yes_type check_sig(D const volatile *, long); 00083 #endif 00084 static __no_type check_sig(B const volatile *, int); 00085 }; 00086 00087 /// \if internal_doc 00088 /// \class IsBaseAndDerived 00089 /// check if the second template argument is derived from the first one 00090 /// 00091 /// this class has 2 template dependencies: B and D. It contains a 00092 /// static boolean value that will be true if D is derived from B and 00093 /// false otherwise. 00094 /// 00095 /// Note: This construct may have a problem with MSVC7.1. See the 00096 /// boost implementation for a description and workaround 00097 /// \endif 00098 template<typename B, typename D> 00099 struct IsBaseAndDerived{ 00100 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000)) 00101 #pragma warning(push) 00102 #pragma warning(disable:6334) 00103 #endif 00104 00105 00106 /// \if internal_doc 00107 /// a helper structure that will pick between a casting to B*const 00108 /// or D. 00109 /// 00110 /// precisely how this structure works involves advanced C++ 00111 /// conversion rules 00112 /// \endif 00113 struct Host{ 00114 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310)) 00115 operator B const volatile *() const; 00116 #else 00117 operator B const volatile * const&() const; 00118 #endif 00119 operator D const volatile *(); 00120 }; 00121 00122 /// the boolean value being true if D is derived from B 00123 static const bool value = ((sizeof(B)!=0) && (sizeof(D)!=0) && (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type))); 00124 00125 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000)) 00126 #pragma warning(pop) 00127 #endif 00128 }; 00129 00130 FASTJET_END_NAMESPACE 00131 00132 00133 #endif // __IS_BASE_OF_HH__